From b39f8ddaae8800b5f39649cceda3c593ff4d5bc3 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Mon, 26 Aug 2024 09:09:39 -0600 Subject: [PATCH 1/3] feat(tests) Add "multiple exceptions" eof exception 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 --- .../evmone_exceptions.py | 3 + src/ethereum_test_exceptions/exceptions.py | 14 ++++ src/ethereum_test_fixtures/eof.py | 4 +- src/ethereum_test_specs/eof.py | 42 +++++++--- src/ethereum_test_types/eof/v1/__init__.py | 4 +- .../eip3540_eof_v1/container.py | 83 ++++++++++++------- .../test_example_valid_invalid.py | 32 ++++--- .../test_migrated_valid_invalid.py | 51 ++++++------ .../eip3540_eof_v1/test_section_order.py | 52 ++++++++---- .../eip3540_eof_v1/test_section_size.py | 63 +++++++++----- .../eip4200_relative_jumps/test_rjump.py | 4 +- .../eip4200_relative_jumps/test_rjumpi.py | 4 +- .../eip6206_jumpf/test_jumpf_execution.py | 6 +- 13 files changed, 238 insertions(+), 124 deletions(-) diff --git a/src/ethereum_test_exceptions/evmone_exceptions.py b/src/ethereum_test_exceptions/evmone_exceptions.py index 0a166b80f42..a23e27bf85e 100644 --- a/src/ethereum_test_exceptions/evmone_exceptions.py +++ b/src/ethereum_test_exceptions/evmone_exceptions.py @@ -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: diff --git a/src/ethereum_test_exceptions/exceptions.py b/src/ethereum_test_exceptions/exceptions.py index a4195b77831..f8bde03fc7b 100644 --- a/src/ethereum_test_exceptions/exceptions.py +++ b/src/ethereum_test_exceptions/exceptions.py @@ -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 + """ """ @@ -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), +] diff --git a/src/ethereum_test_fixtures/eof.py b/src/ethereum_test_fixtures/eof.py index 8c53871cead..987cea8ea0b 100644 --- a/src/ethereum_test_fixtures/eof.py +++ b/src/ethereum_test_fixtures/eof.py @@ -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 @@ -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: diff --git a/src/ethereum_test_specs/eof.py b/src/ethereum_test_specs/eof.py index 835cb020536..42d2a90da20 100644 --- a/src/ethereum_test_specs/eof.py +++ b/src/ethereum_test_specs/eof.py @@ -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 @@ -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]] = [ @@ -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, *, diff --git a/src/ethereum_test_types/eof/v1/__init__.py b/src/ethereum_test_types/eof/v1/__init__.py index 07dad0b1fbb..189b5a05143 100644 --- a/src/ethereum_test_types/eof/v1/__init__.py +++ b/src/ethereum_test_types/eof/v1/__init__.py @@ -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 @@ -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. diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/container.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/container.py index ec527e3275f..f758d349c8e 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/container.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/container.py @@ -27,7 +27,7 @@ Section.Code(Op.STOP), ], auto_data_section=False, - validity_error=EOFException.MISSING_DATA_SECTION, + validity_error=[EOFException.MISSING_DATA_SECTION, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="incomplete_magic", @@ -37,7 +37,7 @@ Container( name="no_version", raw_bytes=bytes([0xEF, 0x00]), - validity_error=EOFException.INVALID_VERSION, + validity_error=[EOFException.INVALID_VERSION, EOFException.INVALID_MAGIC], ), Container( name="no_type_header", @@ -51,12 +51,15 @@ [0xEF, 0x00, 0x01, 0x01], ), # TODO the exception must be about incomplete section in the header - validity_error=EOFException.MISSING_HEADERS_TERMINATOR, + validity_error=[ + EOFException.MISSING_HEADERS_TERMINATOR, + EOFException.INVALID_TYPE_SECTION_SIZE, + ], ), Container( name="no_code_header", raw_bytes=bytes([0xEF, 0x00, 0x01, 0x01, 0x00, 0x04, 0xFE]), - validity_error=EOFException.MISSING_CODE_HEADER, + validity_error=[EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="code_section_size_incomplete_1", @@ -71,12 +74,12 @@ Container( name="code_section_size_incomplete_3", raw_bytes=bytes([0xEF, 0x00, 0x01, 0x01, 0x00, 0x04, 0x02, 0x00, 0x01]), - validity_error=EOFException.MISSING_HEADERS_TERMINATOR, + validity_error=[EOFException.MISSING_HEADERS_TERMINATOR, EOFException.ZERO_SECTION_SIZE], ), Container( name="code_section_size_incomplete_4", raw_bytes=bytes([0xEF, 0x00, 0x01, 0x01, 0x00, 0x04, 0x02, 0x00, 0x01, 0x00]), - validity_error=EOFException.INCOMPLETE_SECTION_SIZE, + validity_error=[EOFException.INCOMPLETE_SECTION_SIZE, EOFException.ZERO_SECTION_SIZE], ), Container( name="code_section_count_0x8000_truncated", @@ -167,7 +170,7 @@ auto_data_section=False, auto_type_section=AutoSection.NONE, expected_bytecode="ef0001 00", - validity_error=EOFException.MISSING_TYPE_HEADER, + validity_error=[EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="no_code_section", @@ -176,7 +179,7 @@ Section.Data("0x00"), ], auto_type_section=AutoSection.NONE, - validity_error=EOFException.MISSING_CODE_HEADER, + validity_error=[EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="too_many_code_sections", @@ -213,7 +216,7 @@ 0x00, ] ), - validity_error=EOFException.ZERO_SECTION_SIZE, + validity_error=[EOFException.ZERO_SECTION_SIZE, EOFException.INCOMPLETE_SECTION_NUMBER], ), # The basic `no_section_terminator` cases just remove the terminator # and the `00` for zeroth section inputs looks like one. Error is because @@ -222,13 +225,19 @@ name="no_section_terminator", header_terminator=bytes(), sections=[Section.Code(code=Op.STOP)], - validity_error=EOFException.INVALID_SECTION_BODIES_SIZE, + validity_error=[ + EOFException.INVALID_SECTION_BODIES_SIZE, + EOFException.INVALID_FIRST_SECTION_TYPE, + ], ), Container( name="no_section_terminator_1", header_terminator=bytes(), sections=[Section.Code(code=Op.STOP, custom_size=2)], - validity_error=EOFException.INVALID_SECTION_BODIES_SIZE, + validity_error=[ + EOFException.INVALID_SECTION_BODIES_SIZE, + EOFException.INVALID_FIRST_SECTION_TYPE, + ], ), Container( name="no_section_terminator_2", @@ -240,7 +249,10 @@ name="no_section_terminator_3", header_terminator=bytes(), sections=[Section.Code(code=Op.PUSH1(0) + Op.STOP)], - validity_error=EOFException.INVALID_SECTION_BODIES_SIZE, + validity_error=[ + EOFException.INVALID_SECTION_BODIES_SIZE, + EOFException.INVALID_FIRST_SECTION_TYPE, + ], ), # The following cases just remove the terminator # and the `00` for zeroth section inputs looks like one. Section bodies @@ -263,31 +275,31 @@ name="no_section_terminator_nonzero", header_terminator=b"01", sections=[Section.Code(code=Op.STOP)], - validity_error=EOFException.MISSING_TERMINATOR, + validity_error=[EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="no_section_terminator_nonzero_1", header_terminator=b"02", sections=[Section.Code(code=Op.STOP, custom_size=2)], - validity_error=EOFException.MISSING_TERMINATOR, + validity_error=[EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="no_section_terminator_nonzero_2", header_terminator=b"03", sections=[Section.Code(code="0x", custom_size=3)], - validity_error=EOFException.MISSING_TERMINATOR, + validity_error=[EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="no_section_terminator_nonzero_3", header_terminator=b"04", sections=[Section.Code(code=Op.PUSH1(0) + Op.STOP)], - validity_error=EOFException.MISSING_TERMINATOR, + validity_error=[EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="no_section_terminator_nonzero_4", header_terminator=b"fe", sections=[Section.Code(code=Op.PUSH1(0) + Op.STOP)], - validity_error=EOFException.MISSING_TERMINATOR, + validity_error=[EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="no_code_section_contents", @@ -347,20 +359,23 @@ Section.Data(data="0xDEADBEEF"), Section.Code(Op.STOP), ], - validity_error=EOFException.MISSING_CODE_HEADER, + validity_error=[EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="data_section_without_code_section", sections=[Section.Data(data="0xDEADBEEF")], # TODO the actual exception should be EOFException.MISSING_CODE_HEADER - validity_error=EOFException.ZERO_SECTION_SIZE, + validity_error=[EOFException.ZERO_SECTION_SIZE, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="no_section_terminator_3a", header_terminator=bytes(), sections=[Section.Code(code="0x030004")], # TODO the exception must be about terminator - validity_error=EOFException.INVALID_SECTION_BODIES_SIZE, + validity_error=[ + EOFException.INVALID_SECTION_BODIES_SIZE, + EOFException.INVALID_FIRST_SECTION_TYPE, + ], ), Container( name="no_section_terminator_4a", @@ -389,7 +404,7 @@ Section.Data(data="0xAABBCC"), Section.Data(data="0xAABBCC"), ], - validity_error=EOFException.MISSING_TERMINATOR, + validity_error=[EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="multiple_code_and_data_sections", @@ -399,7 +414,7 @@ Section.Data(data="0xAA"), Section.Data(data="0xAA"), ], - validity_error=EOFException.MISSING_TERMINATOR, + validity_error=[EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="unknown_section_1", @@ -408,7 +423,7 @@ Section.Data(data="0x"), Section(kind=VERSION_MAX_SECTION_KIND + 1, data="0x01"), ], - validity_error=EOFException.MISSING_TERMINATOR, + validity_error=[EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="unknown_section_2", @@ -418,7 +433,7 @@ Section.Code(Op.STOP), ], # TODO the exception should be about unknown section definition - validity_error=EOFException.MISSING_TERMINATOR, + validity_error=[EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="unknown_section_empty", @@ -427,7 +442,7 @@ Section.Data(data="0x"), Section(kind=VERSION_MAX_SECTION_KIND + 1, data="0x"), ], - validity_error=EOFException.MISSING_TERMINATOR, + validity_error=[EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="no_type_section", @@ -436,7 +451,7 @@ Section.Data("0x00"), ], auto_type_section=AutoSection.NONE, - validity_error=EOFException.MISSING_TYPE_HEADER, + validity_error=[EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="too_many_type_sections", @@ -446,7 +461,7 @@ Section.Code(Op.STOP), ], auto_type_section=AutoSection.NONE, - validity_error=EOFException.MISSING_CODE_HEADER, + validity_error=[EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="empty_type_section", @@ -456,7 +471,7 @@ ], auto_type_section=AutoSection.NONE, # TODO the exception must be about type section EOFException.INVALID_TYPE_SECTION_SIZE, - validity_error=EOFException.ZERO_SECTION_SIZE, + validity_error=[EOFException.ZERO_SECTION_SIZE, EOFException.INVALID_SECTION_BODIES_SIZE], ), Container( name="type_section_too_small_1", @@ -590,7 +605,7 @@ Section.Code(Op.STOP), ], auto_sort_sections=AutoSection.NONE, - validity_error=EOFException.MISSING_CODE_HEADER, + validity_error=[EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ), Container( name="data_section_listed_in_type", @@ -598,7 +613,10 @@ Section.Data(data="0x00", force_type_listing=True), Section.Code(Op.STOP), ], - validity_error=EOFException.INVALID_TYPE_SECTION_SIZE, + validity_error=[ + EOFException.INVALID_TYPE_SECTION_SIZE, + EOFException.INVALID_SECTION_BODIES_SIZE, + ], ), Container( name="single_code_section_incomplete_type", @@ -606,7 +624,10 @@ Section(kind=SectionKind.TYPE, data="0x00", custom_size=2), Section.Code(Op.STOP), ], - validity_error=EOFException.INVALID_SECTION_BODIES_SIZE, + validity_error=[ + EOFException.INVALID_SECTION_BODIES_SIZE, + EOFException.INVALID_TYPE_SECTION_SIZE, + ], ), Container( name="single_code_section_input_too_large", diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_example_valid_invalid.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_example_valid_invalid.py index e90e386ef2a..560ec8d51f2 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_example_valid_invalid.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_example_valid_invalid.py @@ -4,6 +4,7 @@ import pytest +from ethereum_test_exceptions.exceptions import EOFExceptionInstanceOrList from ethereum_test_tools import EOFException, EOFTestFiller from ethereum_test_tools import Opcodes as Op from ethereum_test_tools.eof.v1 import Container, Section @@ -62,7 +63,7 @@ header_terminator=b"\xFF", ), "ef00010100040200010003040001ff00800001305000ef", - EOFException.MISSING_TERMINATOR, + [EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], id="headers_terminator_invalid", ), pytest.param( @@ -265,55 +266,60 @@ def test_example_valid_invalid( "skip_header_listing, skip_body_listing, skip_types_body_listing, skip_types_header_listing," "expected_code, expected_exception", [ - ( - # Data 16 test case of valid invalid eof ori filler + pytest.param( True, # second section is not in code header array True, # second section is not in container's body (it's code bytes) False, # but it's code input bytes still listed in container's body False, # but it's code input bytes size still added to types section size "ef000101000802000100030400040000800001000000003050000bad60A7", - EOFException.INVALID_TYPE_SECTION_SIZE, + [EOFException.INVALID_TYPE_SECTION_SIZE, EOFException.INVALID_SECTION_BODIES_SIZE], + id="drop_code_section_and_header", ), - ( + pytest.param( True, # second section is not in code header array False, # second section code is in container's body (3050000) False, # but it's code input bytes still listed in container's body False, # but it's code input bytes size still added to types section size "ef000101000802000100030400040000800001000000003050003050000bad60A7", - EOFException.INVALID_TYPE_SECTION_SIZE, + [EOFException.INVALID_TYPE_SECTION_SIZE, EOFException.INVALID_SECTION_BODIES_SIZE], + id="drop_code_header", ), - ( + pytest.param( False, # second section is mentioned in code header array (0003) True, # second section is not in container's body (it's code bytes) False, # but it's code input bytes still listed in container's body False, # but it's code input bytes size still added to types section size "ef0001010008020002000300030400040000800001000000003050000bad60A7", - EOFException.UNREACHABLE_CODE_SECTIONS, + [EOFException.UNREACHABLE_CODE_SECTIONS, EOFException.TOPLEVEL_CONTAINER_TRUNCATED], + id="drop_code_section", ), - ( + pytest.param( False, # second section is mentioned in code header array (0003) False, # second section code is in container's body (3050000) False, # but it's code input bytes still listed in container's body False, # but it's code input bytes size still added to types section size "ef0001010008020002000300030400040000800001000000003050003050000bad60A7", EOFException.UNREACHABLE_CODE_SECTIONS, + id="layout_ok_code_bad", ), - ( + pytest.param( # Data 17 test case of valid invalid eof ori filler True, # second section is not in code header array True, # second section is not in container's body (it's code bytes) True, # it's code input bytes are not listed in container's body (00000000) False, # but it's code input bytes size still added to types section size "ef0001010008020001000304000400008000013050000bad60a7", - EOFException.INVALID_TYPE_SECTION_SIZE, + [EOFException.INVALID_TYPE_SECTION_SIZE, EOFException.INVALID_SECTION_BODIES_SIZE], + id="drop_types_header", ), - ( + pytest.param( True, # second section is not in code header array True, # second section is not in container's body (it's code bytes) True, # it's code input bytes are not listed in container's body (00000000) True, # and it is bytes size is not counted in types header "ef0001010004020001000304000400008000013050000bad60a7", None, + id="drop_everything", ), ], ) @@ -324,7 +330,7 @@ def test_code_section_header_body_mismatch( skip_types_body_listing: bool, skip_types_header_listing: bool, expected_code: str, - expected_exception: EOFException | None, + expected_exception: EOFExceptionInstanceOrList | None, ): """ Inconsistent number of code sections (between types and code) diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_migrated_valid_invalid.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_migrated_valid_invalid.py index 6633b9093da..017bd9a1cc6 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_migrated_valid_invalid.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_migrated_valid_invalid.py @@ -5,6 +5,7 @@ import pytest +from ethereum_test_exceptions.exceptions import EOFExceptionInstanceOrList from ethereum_test_tools import EOFException, EOFTestFiller from ethereum_test_tools import Opcodes as Op from ethereum_test_tools.eof.v1 import Container, Section @@ -70,7 +71,7 @@ pytest.param( # Type section size incomplete bytes.fromhex("ef00010100"), - EOFException.INCOMPLETE_SECTION_SIZE, + [EOFException.INCOMPLETE_SECTION_SIZE, EOFException.INVALID_TYPE_SECTION_SIZE], id="EOF1I3540_0011_type_section_size_incomplete", ), pytest.param( @@ -95,7 +96,7 @@ name="EOF1I3540_0016 (Invalid) Code section size incomplete", raw_bytes="0xef000101000402000100", ), - EOFException.INCOMPLETE_SECTION_SIZE, + [EOFException.INCOMPLETE_SECTION_SIZE, EOFException.ZERO_SECTION_SIZE], id="EOF1I3540_0016_code_section_size_incomplete", ), pytest.param( @@ -107,13 +108,13 @@ pytest.param( # No data size bytes.fromhex("ef0001010004020001000104"), - EOFException.MISSING_HEADERS_TERMINATOR, + [EOFException.MISSING_HEADERS_TERMINATOR, EOFException.INCOMPLETE_DATA_HEADER], id="EOF1I3540_0018_no_data_size", ), pytest.param( # Data size incomplete bytes.fromhex("ef000101000402000100010400"), - EOFException.INCOMPLETE_SECTION_SIZE, + [EOFException.INCOMPLETE_SECTION_SIZE, EOFException.INCOMPLETE_DATA_HEADER], id="EOF1I3540_0019_data_size_incomplete", ), pytest.param( @@ -179,31 +180,31 @@ pytest.param( # Code section preceding type section bytes.fromhex("ef000102000100010100040400020000000000feaabb"), - EOFException.MISSING_TYPE_HEADER, + [EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0030_code_section_preceding_type_section", ), pytest.param( # Data section preceding type section bytes.fromhex("ef000104000201000402000100010000000000feaabb"), - EOFException.MISSING_TYPE_HEADER, + [EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0031_data_section_preceding_type_section", ), pytest.param( # Data section preceding code section bytes.fromhex("ef000101000404000202000100010000000000feaabb"), - EOFException.MISSING_CODE_HEADER, + [EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0032_data_section_preceding_code_section", ), pytest.param( # Data section without code section bytes.fromhex("ef00010100040400020000000000aabb"), - EOFException.MISSING_CODE_HEADER, + [EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0033_data_section_without_code_section", ), pytest.param( # No data section bytes.fromhex("ef000101000402000100010000000000fe"), - EOFException.MISSING_DATA_SECTION, + [EOFException.MISSING_DATA_SECTION, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0034_no_data_section", ), pytest.param( @@ -228,85 +229,85 @@ pytest.param( # Multiple data sections bytes.fromhex("ef000101000402000100010400020400020000000000feaabbaabb"), - EOFException.MISSING_TERMINATOR, + [EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0036_multiple_data_sections", ), pytest.param( # Multiple code and data sections bytes.fromhex("ef000101000802000200010001040002040002000000000000000000fefeaabbaabb"), - EOFException.MISSING_TERMINATOR, + [EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0037_multiple_code_and_data_sections", ), pytest.param( # Unknown section ID (at the beginning) bytes.fromhex("ef000105000101000402000100010400000000000000fe"), - EOFException.MISSING_TYPE_HEADER, + [EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0038_unknown_section_id_at_the_beginning_05", ), pytest.param( # Unknown section ID (at the beginning) bytes.fromhex("ef000106000101000402000100010400000000000000fe"), - EOFException.MISSING_TYPE_HEADER, + [EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0039_unknown_section_id_at_the_beginning_06", ), pytest.param( # Unknown section ID (at the beginning) bytes.fromhex("ef0001ff000101000402000100010400000000000000fe"), - EOFException.MISSING_TYPE_HEADER, + [EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0040_unknown_section_id_at_the_beginning_ff", ), pytest.param( # Unknown section ID (after types section) bytes.fromhex("ef000101000405000102000100010400000000000000fe"), - EOFException.MISSING_CODE_HEADER, + [EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0041_unknown_section_id_after_types_section_05", ), pytest.param( # Unknown section ID (after types section) bytes.fromhex("ef000101000406000102000100010400000000000000fe"), - EOFException.MISSING_CODE_HEADER, + [EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0042_unknown_section_id_after_types_section_06", ), pytest.param( # Unknown section ID (after types section) bytes.fromhex("ef0001010004ff000102000100010400000000000000fe"), - EOFException.MISSING_CODE_HEADER, + [EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0043_unknown_section_id_after_types_section_ff", ), pytest.param( # Unknown section ID (after code section) bytes.fromhex("ef000101000402000100010500010400000000000000fe"), - EOFException.MISSING_DATA_SECTION, + [EOFException.MISSING_DATA_SECTION, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0044_unknown_section_id_after_code_section_05", ), pytest.param( # Unknown section ID (after code section) bytes.fromhex("ef000101000402000100010600010400000000000000fe"), - EOFException.MISSING_DATA_SECTION, + [EOFException.MISSING_DATA_SECTION, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0045_unknown_section_id_after_code_section_06", ), pytest.param( # Unknown section ID (after code section) bytes.fromhex("ef00010100040200010001ff00010400000000000000fe"), - EOFException.MISSING_DATA_SECTION, + [EOFException.MISSING_DATA_SECTION, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0046_unknown_section_id_after_code_section_ff", ), pytest.param( # Unknown section ID (after data section) bytes.fromhex("ef000101000402000100010400000500010000000000fe"), - EOFException.MISSING_TERMINATOR, + [EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0047_unknown_section_id_after_data_section_05", ), pytest.param( # Unknown section ID (after data section) bytes.fromhex("ef000101000402000100010400000600010000000000fe"), - EOFException.MISSING_TERMINATOR, + [EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0048_unknown_section_id_after_data_section_06", ), pytest.param( # Unknown section ID (after data section) bytes.fromhex("ef00010100040200010001040000ff00010000000000fe"), - EOFException.MISSING_TERMINATOR, + [EOFException.MISSING_TERMINATOR, EOFException.UNEXPECTED_HEADER_KIND], id="EOF1I3540_0049_unknown_section_id_after_data_section_ff", ), # TODO: Duplicated tests @@ -348,7 +349,7 @@ name="EOF1I3540_0005 (Invalid) No version", raw_bytes="ef00", ), - EOFException.INVALID_VERSION, + [EOFException.INVALID_VERSION, EOFException.INVALID_MAGIC], id="EOF1I3540_0005_invalid_no_version", ), pytest.param( @@ -380,7 +381,7 @@ def test_migrated_valid_invalid( eof_test: EOFTestFiller, eof_code: Container | bytes, - exception: EOFException | None, + exception: EOFExceptionInstanceOrList | None, ): """ Verify EOF container construction and exception diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py index d0f3703617e..f3ba13bea75 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py @@ -7,6 +7,7 @@ import pytest +from ethereum_test_exceptions.exceptions import EOFExceptionInstanceOrList from ethereum_test_tools import EOFException, EOFTestFiller from ethereum_test_tools import Opcodes as Op from ethereum_test_tools.eof.v1 import AutoSection, Container, Section, SectionKind @@ -40,24 +41,33 @@ class CasePosition(Enum): def get_expected_code_exception( section_kind, section_test, test_position -) -> tuple[str, EOFException | None]: +) -> tuple[str, EOFExceptionInstanceOrList | None]: """ Verification vectors with code and exception based on test combinations """ match (section_kind, section_test, test_position): case (SectionKind.TYPE, SectionTest.MISSING, CasePosition.HEADER): - return "ef000102000100030400010000800001305000ef", EOFException.MISSING_TYPE_HEADER + return ( + "ef000102000100030400010000800001305000ef", + [EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], + ) case (SectionKind.TYPE, SectionTest.MISSING, CasePosition.BODY): return ( "ef0001010004020001000304000100305000ef", - EOFException.INVALID_SECTION_BODIES_SIZE, + [ + EOFException.INVALID_SECTION_BODIES_SIZE, + EOFException.INVALID_FIRST_SECTION_TYPE, + ], ) case (SectionKind.TYPE, SectionTest.MISSING, CasePosition.BODY_AND_HEADER): - return "ef0001020001000304000100305000ef", EOFException.MISSING_TYPE_HEADER + return ( + "ef0001020001000304000100305000ef", + [EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], + ) case (SectionKind.TYPE, SectionTest.WRONG_ORDER, CasePosition.HEADER): return ( "ef000102000100030100040400010000800001305000ef", - EOFException.MISSING_TYPE_HEADER, + [EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ) case (SectionKind.TYPE, SectionTest.WRONG_ORDER, CasePosition.BODY): return ( @@ -68,23 +78,29 @@ def get_expected_code_exception( case (SectionKind.TYPE, SectionTest.WRONG_ORDER, CasePosition.BODY_AND_HEADER): return ( "ef000102000100030100040400010030500000800001ef", - EOFException.MISSING_TYPE_HEADER, + [EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ) case (SectionKind.CODE, SectionTest.MISSING, CasePosition.HEADER): - return "ef00010100040400010000800001305000ef", EOFException.MISSING_CODE_HEADER + return ( + "ef00010100040400010000800001305000ef", + [EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], + ) case (SectionKind.CODE, SectionTest.MISSING, CasePosition.BODY): return ( "ef000101000402000100030400010000800001ef", # TODO should be an exception of empty code bytes, because it can understand that # last byte is data section byte - EOFException.INVALID_SECTION_BODIES_SIZE, + [EOFException.INVALID_SECTION_BODIES_SIZE, EOFException.UNEXPECTED_HEADER_KIND], ) case (SectionKind.CODE, SectionTest.MISSING, CasePosition.BODY_AND_HEADER): - return "ef00010100040400010000800001ef", EOFException.MISSING_CODE_HEADER + return ( + "ef00010100040400010000800001ef", + [EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], + ) case (SectionKind.CODE, SectionTest.WRONG_ORDER, CasePosition.HEADER): return ( "ef000101000404000102000100030000800001305000ef", - EOFException.MISSING_CODE_HEADER, + [EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ) case (SectionKind.CODE, SectionTest.WRONG_ORDER, CasePosition.BODY): return ( @@ -94,21 +110,27 @@ def get_expected_code_exception( case (SectionKind.CODE, SectionTest.WRONG_ORDER, CasePosition.BODY_AND_HEADER): return ( "ef000101000404000102000100030000800001ef305000", - EOFException.MISSING_CODE_HEADER, + [EOFException.MISSING_CODE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ) case (SectionKind.DATA, SectionTest.MISSING, CasePosition.HEADER): - return "ef000101000402000100030000800001305000ef", EOFException.MISSING_DATA_SECTION + return ( + "ef000101000402000100030000800001305000ef", + [EOFException.MISSING_DATA_SECTION, EOFException.UNEXPECTED_HEADER_KIND], + ) case (SectionKind.DATA, SectionTest.MISSING, CasePosition.BODY): return ( "ef000101000402000100030400010000800001305000", EOFException.TOPLEVEL_CONTAINER_TRUNCATED, ) case (SectionKind.DATA, SectionTest.MISSING, CasePosition.BODY_AND_HEADER): - return "ef000101000402000100030000800001305000", EOFException.MISSING_DATA_SECTION + return ( + "ef000101000402000100030000800001305000", + [EOFException.MISSING_DATA_SECTION, EOFException.UNEXPECTED_HEADER_KIND], + ) case (SectionKind.DATA, SectionTest.WRONG_ORDER, CasePosition.HEADER): return ( "ef000104000101000402000100030000800001305000ef", - EOFException.MISSING_TYPE_HEADER, + [EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ) case (SectionKind.DATA, SectionTest.WRONG_ORDER, CasePosition.BODY): return ( @@ -118,7 +140,7 @@ def get_expected_code_exception( case (SectionKind.DATA, SectionTest.WRONG_ORDER, CasePosition.BODY_AND_HEADER): return ( "ef0001040001010004020001000300ef00800001305000", - EOFException.MISSING_TYPE_HEADER, + [EOFException.MISSING_TYPE_HEADER, EOFException.UNEXPECTED_HEADER_KIND], ) return "", None diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py index 72fe5f169b9..f5c3412d998 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py @@ -6,6 +6,7 @@ import pytest +from ethereum_test_exceptions.exceptions import EOFExceptionInstanceOrList from ethereum_test_tools import EOFException, EOFTestFiller from ethereum_test_tools import Opcodes as Op from ethereum_test_tools.eof.v1 import Container, Section, SectionKind @@ -40,31 +41,55 @@ def __str__(self) -> str: @pytest.mark.parametrize( "section_kind, section_size, exception", [ - (SectionKind.DATA, SectionSize.NORMAL, None), - (SectionKind.DATA, SectionSize.ZERO, EOFException.INVALID_SECTION_BODIES_SIZE), - (SectionKind.DATA, SectionSize.UNDERSIZE, EOFException.INVALID_SECTION_BODIES_SIZE), - (SectionKind.DATA, SectionSize.OVERSIZE, EOFException.TOPLEVEL_CONTAINER_TRUNCATED), - (SectionKind.DATA, SectionSize.HUGE, EOFException.TOPLEVEL_CONTAINER_TRUNCATED), - (SectionKind.DATA, SectionSize.MAX, EOFException.TOPLEVEL_CONTAINER_TRUNCATED), - (SectionKind.CODE, SectionSize.NORMAL, None), - (SectionKind.CODE, SectionSize.ZERO, EOFException.ZERO_SECTION_SIZE), - (SectionKind.CODE, SectionSize.UNDERSIZE, EOFException.INVALID_SECTION_BODIES_SIZE), - (SectionKind.CODE, SectionSize.OVERSIZE, EOFException.INVALID_SECTION_BODIES_SIZE), - (SectionKind.CODE, SectionSize.HUGE, EOFException.INVALID_SECTION_BODIES_SIZE), - (SectionKind.CODE, SectionSize.MAX, EOFException.INVALID_SECTION_BODIES_SIZE), - (SectionKind.TYPE, SectionSize.NORMAL, None), - (SectionKind.TYPE, SectionSize.ZERO, EOFException.ZERO_SECTION_SIZE), - (SectionKind.TYPE, SectionSize.UNDERSIZE, EOFException.INVALID_TYPE_SECTION_SIZE), - (SectionKind.TYPE, SectionSize.OVERSIZE, EOFException.INVALID_SECTION_BODIES_SIZE), - (SectionKind.TYPE, SectionSize.HUGE, EOFException.INVALID_SECTION_BODIES_SIZE), - (SectionKind.TYPE, SectionSize.MAX, EOFException.INVALID_SECTION_BODIES_SIZE), + pytest.param(SectionKind.DATA, SectionSize.NORMAL, None), + pytest.param(SectionKind.DATA, SectionSize.ZERO, EOFException.INVALID_SECTION_BODIES_SIZE), + pytest.param( + SectionKind.DATA, SectionSize.UNDERSIZE, EOFException.INVALID_SECTION_BODIES_SIZE + ), + pytest.param( + SectionKind.DATA, SectionSize.OVERSIZE, EOFException.TOPLEVEL_CONTAINER_TRUNCATED + ), + pytest.param( + SectionKind.DATA, SectionSize.HUGE, EOFException.TOPLEVEL_CONTAINER_TRUNCATED + ), + pytest.param(SectionKind.DATA, SectionSize.MAX, EOFException.TOPLEVEL_CONTAINER_TRUNCATED), + pytest.param(SectionKind.CODE, SectionSize.NORMAL, None), + pytest.param(SectionKind.CODE, SectionSize.ZERO, EOFException.ZERO_SECTION_SIZE), + pytest.param( + SectionKind.CODE, SectionSize.UNDERSIZE, EOFException.INVALID_SECTION_BODIES_SIZE + ), + pytest.param( + SectionKind.CODE, SectionSize.OVERSIZE, EOFException.INVALID_SECTION_BODIES_SIZE + ), + pytest.param(SectionKind.CODE, SectionSize.HUGE, EOFException.INVALID_SECTION_BODIES_SIZE), + pytest.param(SectionKind.CODE, SectionSize.MAX, EOFException.INVALID_SECTION_BODIES_SIZE), + pytest.param(SectionKind.TYPE, SectionSize.NORMAL, None), + pytest.param( + SectionKind.TYPE, + SectionSize.ZERO, + [EOFException.ZERO_SECTION_SIZE, EOFException.INVALID_SECTION_BODIES_SIZE], + id="type_size_zero", + ), + pytest.param( + SectionKind.TYPE, SectionSize.UNDERSIZE, EOFException.INVALID_TYPE_SECTION_SIZE + ), + pytest.param( + SectionKind.TYPE, SectionSize.OVERSIZE, EOFException.INVALID_SECTION_BODIES_SIZE + ), + pytest.param(SectionKind.TYPE, SectionSize.HUGE, EOFException.INVALID_SECTION_BODIES_SIZE), + pytest.param( + SectionKind.TYPE, + SectionSize.MAX, + [EOFException.INVALID_SECTION_BODIES_SIZE, EOFException.INVALID_TYPE_SECTION_SIZE], + id="type_size_max", + ), ], ) def test_section_size( eof_test: EOFTestFiller, section_size: SectionSize, section_kind: SectionKind, - exception: EOFException, + exception: EOFExceptionInstanceOrList, ): """ Test custom_size is auto, more or less then the actual size of the section diff --git a/tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py b/tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py index 2e0f765500d..7b2fe247b95 100644 --- a/tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py +++ b/tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py @@ -408,7 +408,7 @@ def test_rjump_into_push_1(eof_test: EOFTestFiller, jump: JumpDirection): """EOF1I4200_0011 (Invalid) EOF code containing RJUMP with target PUSH1 immediate""" code = ( Op.PUSH1[1] + Op.RJUMP[-4] if jump == JumpDirection.BACKWARD else Op.RJUMP[1] + Op.PUSH1[1] - ) + ) + Op.STOP eof_test( data=Container( sections=[ @@ -471,7 +471,7 @@ def test_rjump_into_push_n( data_portion_length = int.from_bytes(opcode, byteorder="big") - 0x5F if jump == JumpDirection.FORWARD: offset = data_portion_length if data_portion_end else 1 - code = Op.RJUMP[offset] + opcode[0] + code = Op.RJUMP[offset] + opcode[0] + Op.STOP else: offset = -4 if data_portion_end else -4 - data_portion_length + 1 code = opcode[0] + Op.RJUMP[offset] diff --git a/tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py b/tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py index e8f7d2fc6c4..10cfa17521a 100644 --- a/tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py +++ b/tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py @@ -605,10 +605,10 @@ def test_rjumpi_into_push_n( data_portion_length = int.from_bytes(opcode, byteorder="big") - 0x5F if jump == JumpDirection.FORWARD: offset = data_portion_length if data_portion_end else 1 - code = Op.PUSH1(1) + Op.RJUMPI[offset] + opcode[0] + code = Op.PUSH1(1) + Op.RJUMPI[offset] + opcode[0] + Op.STOP else: offset = -4 if data_portion_end else -4 - data_portion_length + 1 - code = opcode[0] + Op.RJUMPI[offset] + code = opcode[0] + Op.RJUMPI[offset] + Op.STOP eof_test( data=Container( sections=[ diff --git a/tests/prague/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py b/tests/prague/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py index 84d41c6ec1b..611d528c621 100644 --- a/tests/prague/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py +++ b/tests/prague/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py @@ -96,7 +96,7 @@ def test_jumpf_too_large( code=Op.JUMPF[1025], ) ], - validity_error=EOFException.UNDEFINED_EXCEPTION, + validity_error=EOFException.INVALID_CODE_SECTION_INDEX, ), ) @@ -112,7 +112,7 @@ def test_jumpf_way_too_large( code=Op.JUMPF[0xFFFF], ) ], - validity_error=EOFException.UNDEFINED_EXCEPTION, + validity_error=EOFException.INVALID_CODE_SECTION_INDEX, ), ) @@ -128,7 +128,7 @@ def test_jumpf_to_nonexistent_section( code=Op.JUMPF[5], ) ], - validity_error=EOFException.UNDEFINED_EXCEPTION, + validity_error=EOFException.INVALID_CODE_SECTION_INDEX, ), ) From fae715dc12ad425f799f29c2fbec84a5588862ad Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Mon, 26 Aug 2024 17:38:54 -0600 Subject: [PATCH 2/3] review comments Signed-off-by: Danno Ferrin --- src/ethereum_test_exceptions/__init__.py | 6 ++-- src/ethereum_test_specs/eof.py | 37 ++++++------------------ 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/src/ethereum_test_exceptions/__init__.py b/src/ethereum_test_exceptions/__init__.py index fbe45d29622..33cdb29f51e 100644 --- a/src/ethereum_test_exceptions/__init__.py +++ b/src/ethereum_test_exceptions/__init__.py @@ -8,6 +8,7 @@ BlockException, BlockExceptionInstanceOrList, EOFException, + EOFExceptionInstanceOrList, ExceptionInstanceOrList, TransactionException, TransactionExceptionInstanceOrList, @@ -16,10 +17,11 @@ __all__ = [ "BlockException", "BlockExceptionInstanceOrList", - "EngineAPIError", "EOFException", + "EOFExceptionInstanceOrList", + "EngineAPIError", + "EvmoneExceptionMapper", "ExceptionInstanceOrList", "TransactionException", "TransactionExceptionInstanceOrList", - "EvmoneExceptionMapper", ] diff --git a/src/ethereum_test_specs/eof.py b/src/ethereum_test_specs/eof.py index 42d2a90da20..af67fd47ffa 100644 --- a/src/ethereum_test_specs/eof.py +++ b/src/ethereum_test_specs/eof.py @@ -12,7 +12,7 @@ from pydantic import Field, model_validator from ethereum_test_base_types import Account, Bytes -from ethereum_test_exceptions import EOFException, EvmoneExceptionMapper +from ethereum_test_exceptions import 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 @@ -238,40 +238,21 @@ 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", - ) - - for expected in expected_result.exception: - if expected == actual_exception: - return - - raise EOFExceptionMismatch( - code=code, - 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) - + expected_string = to_pipe_str(expected_result.exception) + print(expected_string) + print(actual_exception) if "OK" in actual_message: raise ExpectedEOFException( code=code, - expected=f"{expected_exception} ({expected_message})", - got="balid EOF code", + expected=f"{expected_string}", ) - - if expected_exception != actual_exception: + elif actual_exception in expected_result.exception: + return + else: raise EOFExceptionMismatch( code=code, - expected=f"{expected_exception} ({expected_message})", + expected=f"{expected_string}", got=f"{actual_exception} ({actual_message})", ) From 319e527f79126ce2b862252e1529f3317d9d5e68 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Tue, 27 Aug 2024 00:35:05 +0000 Subject: [PATCH 3/3] docs: changelog --- docs/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 1addb0b41ac..98c56eb2419 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -24,6 +24,7 @@ Test fixtures for use by clients are available for each release on the [Github r - ๐Ÿž Fixed fixture index generation on EOF tests ([#728](https://github.com/ethereum/execution-spec-tests/pull/728)). - ๐Ÿž Fixes consume genesis mismatch exception for hive based simulators ([#734](https://github.com/ethereum/execution-spec-tests/pull/734)). - โœจ Adds reproducible consume commands to hiveview ([#717](https://github.com/ethereum/execution-spec-tests/pull/717)). +- ๐Ÿ’ฅ Added multiple exceptions to the EOF fixture format ([#759](https://github.com/ethereum/execution-spec-tests/pull/759)). ### ๐Ÿ”ง EVM Tools @@ -32,6 +33,10 @@ Test fixtures for use by clients are available for each release on the [Github r - โœจ Feature releases can now include multiple types of fixture tarball files from different releases that start with the same prefix ([#736](https://github.com/ethereum/execution-spec-tests/pull/736)). - โœจ Releases for feature eip7692 now include both Cancun and Prague based tests in the same release, in files `fixtures_eip7692.tar.gz` and `fixtures_eip7692-prague.tar.gz` respectively ([#743](https://github.com/ethereum/execution-spec-tests/pull/743)). +### ๐Ÿ’ฅ Breaking Change + +- The EOF fixture format contained in `eof_tests` may now contain multiple exceptions in the `"exception"` field in the form of a pipe (`|`) separated string ([#759](https://github.com/ethereum/execution-spec-tests/pull/759)). + ## [v3.0.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v3.0.0) - 2024-07-22 ### ๐Ÿงช Test Cases