Skip to content

Commit

Permalink
feat(tests) Add "multiple exceptions" eof exception
Browse files Browse the repository at this point in the history
There are some tests that are impossible to express without causing
multiple validation exceptions. Clients should be free to expose any of
those exceptions. To support this pipe notation for expected exceptions
is plumed through the EOF tests and implemented in some tests.

Signed-off-by: Danno Ferrin <[email protected]>
  • Loading branch information
shemnon committed Aug 26, 2024
1 parent 67a2cac commit b39f8dd
Show file tree
Hide file tree
Showing 13 changed files with 238 additions and 124 deletions.
3 changes: 3 additions & 0 deletions src/ethereum_test_exceptions/evmone_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ class EvmoneExceptionMapper:
),
ExceptionMessage(EOFException.STACK_HEIGHT_MISMATCH, "err: stack_height_mismatch"),
ExceptionMessage(EOFException.TOO_MANY_CONTAINERS, "err: too_many_container_sections"),
ExceptionMessage(
EOFException.INVALID_CODE_SECTION_INDEX, "err: invalid_code_section_index"
),
)

def __init__(self) -> None:
Expand Down
14 changes: 14 additions & 0 deletions src/ethereum_test_exceptions/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,14 @@ class EOFException(ExceptionBase):
"""
EOF container header has too many sub-containers.
"""
INVALID_CODE_SECTION_INDEX = auto()
"""
CALLF Operation referes to a non-existent code section
"""
UNEXPECTED_HEADER_KIND = auto()
"""
Header parsing encounterd a section kind it wasn't expecting
"""


"""
Expand All @@ -753,3 +761,9 @@ class EOFException(ExceptionBase):
BeforeValidator(from_pipe_str),
PlainSerializer(to_pipe_str),
]

EOFExceptionInstanceOrList = Annotated[
List[EOFException] | EOFException,
BeforeValidator(from_pipe_str),
PlainSerializer(to_pipe_str),
]
4 changes: 2 additions & 2 deletions src/ethereum_test_fixtures/eof.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pydantic import Field

from ethereum_test_base_types import Bytes, CamelModel, Number
from ethereum_test_exceptions import EOFException
from ethereum_test_exceptions.exceptions import EOFExceptionInstanceOrList
from ethereum_test_types.eof.v1 import ContainerKind

from .base import BaseFixture
Expand All @@ -20,7 +20,7 @@ class Result(CamelModel):
Result for a single fork in a fixture.
"""

exception: EOFException | None = None
exception: EOFExceptionInstanceOrList | None = None
valid: bool = Field(..., alias="result")

def model_post_init(self, __context: Any) -> None:
Expand Down
42 changes: 32 additions & 10 deletions src/ethereum_test_specs/eof.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from ethereum_test_base_types import Account, Bytes
from ethereum_test_exceptions import EOFException, EvmoneExceptionMapper
from ethereum_test_exceptions.exceptions import EOFExceptionInstanceOrList, to_pipe_str
from ethereum_test_fixtures import BaseFixture, FixtureFormats
from ethereum_test_fixtures.eof import Fixture, Result, Vector
from ethereum_test_forks import Fork
Expand Down Expand Up @@ -136,7 +137,7 @@ class EOFTest(BaseTest):
"""

data: Bytes
expect_exception: EOFException | None = None
expect_exception: EOFExceptionInstanceOrList | None = None
container_kind: ContainerKind | None = None

supported_fixture_formats: ClassVar[List[FixtureFormats]] = [
Expand Down Expand Up @@ -237,22 +238,43 @@ def verify_result(self, result: CompletedProcess, expected_result: Result, code:
raise UnexpectedEOFException(
code=code, got=f"{actual_exception} ({actual_message})"
)
elif isinstance(expected_result.exception, List):
expected_string = to_pipe_str(expected_result.exception)
if "OK" in actual_message:
raise ExpectedEOFException(
code=code,
expected=f"multiple possible exceptions {expected_string}",
got="valid EOF code",
)

expected_exception = expected_result.exception
expected_message = parser.exception_to_message(expected_exception)

if "OK" in actual_message:
raise ExpectedEOFException(
code=code, expected=f"{expected_exception} ({expected_message})"
)
for expected in expected_result.exception:
if expected == actual_exception:
return

if expected_exception != actual_exception:
raise EOFExceptionMismatch(
code=code,
expected=f"{expected_exception} ({expected_message})",
expected=f"multiple possible exceptions {expected_string}",
got=f"{actual_exception} ({actual_message})",
)

else:
expected_exception = expected_result.exception
expected_message = parser.exception_to_message(expected_exception)

if "OK" in actual_message:
raise ExpectedEOFException(
code=code,
expected=f"{expected_exception} ({expected_message})",
got="balid EOF code",
)

if expected_exception != actual_exception:
raise EOFExceptionMismatch(
code=code,
expected=f"{expected_exception} ({expected_message})",
got=f"{actual_exception} ({actual_message})",
)

def generate(
self,
*,
Expand Down
4 changes: 2 additions & 2 deletions src/ethereum_test_types/eof/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from ethereum_test_base_types import Bytes
from ethereum_test_base_types.conversions import BytesConvertible
from ethereum_test_base_types.pydantic import CopyValidateModel
from ethereum_test_exceptions import EOFException
from ethereum_test_exceptions.exceptions import EOFExceptionInstanceOrList
from ethereum_test_vm import Bytecode
from ethereum_test_vm import Opcodes as Op

Expand Down Expand Up @@ -365,7 +365,7 @@ class Container(CopyValidateModel):
Body: type section first, all code sections, data section(s), last
container sections
"""
validity_error: EOFException | str | None = None
validity_error: EOFExceptionInstanceOrList | str | None = None
"""
Optional error expected for the container.
Expand Down
Loading

0 comments on commit b39f8dd

Please sign in to comment.