Skip to content

Commit 09b3688

Browse files
committed
fix(specs): Add unit test for transaction checks
1 parent 0c7d84d commit 09b3688

File tree

2 files changed

+108
-10
lines changed

2 files changed

+108
-10
lines changed

src/ethereum_test_specs/helpers.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
from ethereum_test_types import Transaction, TransactionReceipt
1111

1212

13-
class TransactionExpectedToFailSucceedError(Exception):
14-
"""Exception used when the transaction expected to return an error, did succeed."""
13+
class TransactionUnexpectedSuccessError(Exception):
14+
"""Exception used when the transaction expected to fail succeeded instead."""
1515

1616
def __init__(self, index: int, nonce: int):
1717
"""Initialize the exception with the transaction index and nonce."""
@@ -23,7 +23,7 @@ def __init__(self, index: int, nonce: int):
2323

2424

2525
class TransactionUnexpectedFailError(Exception):
26-
"""Exception used when the transaction expected to succeed, did fail."""
26+
"""Exception used when the transaction expected to succeed failed instead."""
2727

2828
def __init__(self, index: int, nonce: int, message: str, exception: ExceptionBase):
2929
"""Initialize the exception."""
@@ -109,9 +109,7 @@ def verify_transaction_exception(
109109

110110
# info.tx.error is expected error code defined in .py test
111111
if expected_error and not info.t8n_error_message:
112-
raise TransactionExpectedToFailSucceedError(
113-
index=info.transaction_index, nonce=info.tx.nonce
114-
)
112+
raise TransactionUnexpectedSuccessError(index=info.transaction_index, nonce=info.tx.nonce)
115113
elif not expected_error and info.t8n_error_message:
116114
raise TransactionUnexpectedFailError(
117115
index=info.transaction_index,

src/ethereum_test_specs/tests/test_expect.py

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,17 @@
66

77
from ethereum_clis import ExecutionSpecsTransitionTool
88
from ethereum_test_base_types import Account, Address, TestAddress, TestPrivateKey
9-
from ethereum_test_fixtures import StateFixture
9+
from ethereum_test_exceptions import TransactionException
10+
from ethereum_test_fixtures import BlockchainFixture, FixtureFormat, StateFixture
1011
from ethereum_test_forks import Fork, get_deployed_forks
11-
from ethereum_test_types import Alloc, Environment, Storage, Transaction
12+
from ethereum_test_types import Alloc, Environment, Storage, Transaction, TransactionReceipt
1213

14+
from ..helpers import (
15+
TransactionExceptionMismatchError,
16+
TransactionReceiptMismatchError,
17+
TransactionUnexpectedFailError,
18+
TransactionUnexpectedSuccessError,
19+
)
1320
from ..state import StateTest
1421

1522
ADDRESS_UNDER_TEST = Address(0x01)
@@ -24,13 +31,19 @@ def tx() -> Transaction:
2431
@pytest.fixture
2532
def pre(request) -> Alloc:
2633
"""Fixture set from the test's indirectly parametrized `pre` parameter."""
27-
return Alloc(request.param | {TestAddress: Account(balance=(10**18))})
34+
extra_accounts = {}
35+
if hasattr(request, "param"):
36+
extra_accounts = request.param
37+
return Alloc(extra_accounts | {TestAddress: Account(balance=(10**18))})
2838

2939

3040
@pytest.fixture
3141
def post(request) -> Alloc: # noqa: D103
3242
"""Fixture set from the test's indirectly parametrized `post` parameter."""
33-
return Alloc(request.param)
43+
extra_accounts = {}
44+
if hasattr(request, "param"):
45+
extra_accounts = request.param
46+
return Alloc(extra_accounts)
3447

3548

3649
@pytest.fixture
@@ -249,3 +262,90 @@ def test_post_account_mismatch(state_test, t8n, fork, exception_type: Type[Excep
249262
return
250263
with pytest.raises(exception_type) as _:
251264
state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=StateFixture)
265+
266+
267+
# Transaction result mismatch tests
268+
@pytest.mark.run_in_serial
269+
@pytest.mark.parametrize(
270+
"tx,exception_type",
271+
[
272+
pytest.param(
273+
Transaction(
274+
secret_key=TestPrivateKey,
275+
expected_receipt=TransactionReceipt(gas_used=21_000),
276+
),
277+
TransactionExceptionMismatchError,
278+
id="TransactionExceptionMismatchError",
279+
marks=pytest.mark.xfail(
280+
reason="Exceptions need to be better described in the t8n tool."
281+
),
282+
),
283+
pytest.param(
284+
Transaction(
285+
secret_key=TestPrivateKey,
286+
error=TransactionException.INTRINSIC_GAS_TOO_LOW,
287+
expected_receipt=TransactionReceipt(gas_used=21_000),
288+
),
289+
TransactionUnexpectedSuccessError,
290+
id="TransactionUnexpectedSuccessError",
291+
),
292+
pytest.param(
293+
Transaction(
294+
secret_key=TestPrivateKey,
295+
gas_limit=20_999,
296+
expected_receipt=TransactionReceipt(gas_used=21_000),
297+
),
298+
TransactionUnexpectedFailError,
299+
id="TransactionUnexpectedFailError",
300+
),
301+
pytest.param(
302+
Transaction(
303+
secret_key=TestPrivateKey,
304+
expected_receipt=TransactionReceipt(gas_used=21_001),
305+
),
306+
TransactionReceiptMismatchError,
307+
id="TransactionReceiptMismatchError",
308+
),
309+
pytest.param(
310+
Transaction(
311+
secret_key=TestPrivateKey,
312+
gas_limit=20_999,
313+
expected_receipt=TransactionReceipt(gas_used=21_001),
314+
),
315+
TransactionUnexpectedFailError,
316+
id="TransactionUnexpectedFailError+TransactionReceiptMismatchError",
317+
),
318+
pytest.param(
319+
Transaction(
320+
secret_key=TestPrivateKey,
321+
error=TransactionException.INTRINSIC_GAS_TOO_LOW,
322+
expected_receipt=TransactionReceipt(gas_used=21_001),
323+
),
324+
TransactionUnexpectedSuccessError,
325+
id="TransactionUnexpectedSuccessError+TransactionReceiptMismatchError",
326+
),
327+
],
328+
)
329+
@pytest.mark.parametrize(
330+
"fixture_format",
331+
[
332+
StateFixture,
333+
BlockchainFixture,
334+
],
335+
)
336+
def test_transaction_expectation(
337+
state_test,
338+
t8n,
339+
fork,
340+
exception_type: Type[Exception] | None,
341+
fixture_format: FixtureFormat,
342+
):
343+
"""
344+
Test a transaction that has an unexpected error, expected error, or expected a specific
345+
value in its receipt.
346+
"""
347+
if exception_type is None:
348+
state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=fixture_format)
349+
else:
350+
with pytest.raises(exception_type) as _:
351+
state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=fixture_format)

0 commit comments

Comments
 (0)