|
5 | 5 | from pathlib import Path |
6 | 6 | from shutil import which |
7 | 7 | from subprocess import CompletedProcess |
8 | | -from typing import Callable, ClassVar, Dict, Generator, List, Optional, Sequence, Type |
| 8 | +from typing import Annotated, Callable, ClassVar, Dict, Generator, List, Optional, Sequence, Type |
9 | 9 |
|
10 | 10 | import pytest |
11 | | -from pydantic import Field |
| 11 | +from pydantic import Field, TypeAdapter |
12 | 12 |
|
13 | 13 | from ethereum_clis import EvmoneExceptionMapper, TransitionTool |
14 | 14 | from ethereum_test_base_types import Account, Bytes, HexNumber |
| 15 | +from ethereum_test_exceptions import ( |
| 16 | + EOFException, |
| 17 | + ExceptionMapperValidator, |
| 18 | + ExceptionWithMessage, |
| 19 | + UndefinedException, |
| 20 | +) |
15 | 21 | from ethereum_test_exceptions.exceptions import EOFExceptionInstanceOrList, to_pipe_str |
16 | 22 | from ethereum_test_execution import ( |
17 | 23 | BaseExecute, |
@@ -102,6 +108,19 @@ def __init__(self, code: Bytes, expected: str, got: str): |
102 | 108 | super().__init__(message) |
103 | 109 |
|
104 | 110 |
|
| 111 | +class EOFExceptionWithMessage( |
| 112 | + ExceptionWithMessage[EOFException] # type: ignore |
| 113 | +): |
| 114 | + """Exception returned from the eof validator with a message.""" |
| 115 | + |
| 116 | + pass |
| 117 | + |
| 118 | + |
| 119 | +eof_exception_type_adapter: TypeAdapter[EOFExceptionWithMessage | UndefinedException] = ( |
| 120 | + TypeAdapter(Annotated[EOFExceptionWithMessage | UndefinedException, ExceptionMapperValidator]) |
| 121 | +) |
| 122 | + |
| 123 | + |
105 | 124 | class EOFParse: |
106 | 125 | """evmone-eofparse binary.""" |
107 | 126 |
|
@@ -352,33 +371,32 @@ def make_eof_test_fixture( |
352 | 371 |
|
353 | 372 | def verify_result(self, result: CompletedProcess, expected_result: Result, code: Bytes): |
354 | 373 | """Check that the reported exception string matches the expected error.""" |
355 | | - parser = EvmoneExceptionMapper() |
356 | | - actual_message = result.stdout.strip() |
357 | | - actual_exception = parser.message_to_exception(actual_message) |
| 374 | + evmone_exception_mapper = EvmoneExceptionMapper() |
| 375 | + actual_exception_str = result.stdout.strip() |
| 376 | + actual_exception: EOFExceptionWithMessage | UndefinedException | None = None |
| 377 | + if not actual_exception_str.startswith("OK"): |
| 378 | + actual_exception = eof_exception_type_adapter.validate_python( |
| 379 | + actual_exception_str, context={"exception_mapper": evmone_exception_mapper} |
| 380 | + ) |
358 | 381 |
|
359 | 382 | if expected_result.exception is None: |
360 | | - if "OK" in actual_message: |
361 | | - return |
362 | | - else: |
363 | | - raise UnexpectedEOFExceptionError( |
364 | | - code=code, got=f"{actual_exception} ({actual_message})" |
365 | | - ) |
| 383 | + if actual_exception is not None: |
| 384 | + raise UnexpectedEOFExceptionError(code=code, got=f"{actual_exception}") |
366 | 385 | else: |
367 | 386 | expected_string = to_pipe_str(expected_result.exception) |
368 | | - print(expected_string) |
369 | | - print(actual_exception) |
370 | | - if "OK" in actual_message: |
| 387 | + if actual_exception is None: |
371 | 388 | raise ExpectedEOFExceptionError( |
372 | 389 | code=code, |
373 | 390 | expected=f"{expected_string}", |
374 | 391 | ) |
375 | | - elif actual_exception in expected_result.exception: |
376 | | - return |
377 | | - else: |
| 392 | + if ( |
| 393 | + not isinstance(actual_exception, EOFExceptionWithMessage) |
| 394 | + or expected_result.exception not in actual_exception |
| 395 | + ): |
378 | 396 | raise EOFExceptionMismatchError( |
379 | 397 | code=code, |
380 | 398 | expected=f"{expected_string}", |
381 | | - got=f"{actual_exception} ({actual_message})", |
| 399 | + got=f"{actual_exception}", |
382 | 400 | ) |
383 | 401 |
|
384 | 402 | def generate_eof_contract_create_transaction(self) -> Transaction: |
|
0 commit comments