Skip to content

Commit 5064c1c

Browse files
fselmomarioevz
andauthored
feat(tests): Additional EIP-7934 test cases (#1890)
* feat(tests): Add eip7934 test at rlp size with all transaction types * feat(tests): Add eip7934 test at limit with logs * feat(tests,plugins): Add ``with_all_typed_transactions`` support - Create global fixtures for default transactions that are covariant with ``fork`` - These should allow overriding particular default transactions by re-defining the fixture for the particular tx type e.g.: ```python @pytest.fixture def type_2_default_transaction(pre): return Transaction(...) ``` - Use these as part of the ``fork`` plugin * refactor(tests): Use ``with_all_typed_transactions`` for block rlp limit test * refactor(tests) Changes from comments on pr #1890 and offline: - Move transaction fixtures to a `shared` pytest plugin. - Opt for `Type | None` over `Optional[Type]` to avoid an extra import. Bonus: - Refactor the `indirect` marker logic to be more generic for future use. If a marker uses `indirect`, it will take the values from the `fork_attribute_name` and run it through a fixture of name `argnames` which provides some added logic. In this case it builds default transactions from the `tx_types` values for each fork. * chore: Remove duplicate `sender` fixtures; opting for global `sender` * fix(cli/pytest): Ini files imports * fix(pytest_plugins): Paths and imports * chore(docs): Document `with_all_typed_transactions` marker --------- Co-authored-by: Mario Vega <[email protected]>
1 parent cb969b6 commit 5064c1c

File tree

26 files changed

+564
-119
lines changed

26 files changed

+564
-119
lines changed

docs/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ Users can select any of the artifacts depending on their testing needs for their
114114
- ✨ Opcode classes now validate keyword arguments and raise `ValueError` with clear error messages ([#1739](https://github.com/ethereum/execution-spec-tests/pull/1739), [#1856](https://github.com/ethereum/execution-spec-tests/pull/1856)).
115115
- ✨ All commands (`fill`, `consume`, `execute`) now work without having to clone the repository, e.g. `uv run --with git+https://github.com/ethereum/execution-spec-tests.git consume` now works from any folder ([#1863](https://github.com/ethereum/execution-spec-tests/pull/1863)).
116116
- 🔀 Move Prague to stable and Osaka to develop ([#1573](https://github.com/ethereum/execution-spec-tests/pull/1573)).
117+
- ✨ Add a `pytest.mark.with_all_typed_transactions` marker that creates default typed transactions for each `tx_type` supported by the current `fork` ([#1890](https://github.com/ethereum/execution-spec-tests/pull/1890)).
117118

118119
### 🧪 Test Cases
119120

@@ -128,6 +129,7 @@ Users can select any of the artifacts depending on their testing needs for their
128129
-[EIP-7934](https://eips.ethereum.org/EIPS/eip-7934): Add test cases for the block RLP max limit of 10MiB ([#1730](https://github.com/ethereum/execution-spec-tests/pull/1730)).
129130
-[EIP-7939](https://eips.ethereum.org/EIPS/eip-7939) Add count leading zeros (CLZ) opcode tests for Osaka ([#1733](https://github.com/ethereum/execution-spec-tests/pull/1733)).
130131
-[EIP-7918](https://eips.ethereum.org/EIPS/eip-7918): Blob base fee bounded by execution cost test cases (initial), includes some adjustments to [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) tests ([#1685](https://github.com/ethereum/execution-spec-tests/pull/1685)). Update the blob_base_cost ([#1915](https://github.com/ethereum/EIPs/pull/1915)).
132+
-[EIP-7934](https://eips.ethereum.org/EIPS/eip-7934): Add additional test cases for block RLP max limit with all typed transactions and for a log-creating transactions ([#1890](https://github.com/ethereum/execution-spec-tests/pull/1890)).
131133

132134
## [v4.5.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v4.5.0) - 2025-05-14
133135

docs/writing_tests/test_markers.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,59 @@ This marker is used to automatically parameterize a test with all contract creat
5555

5656
This marker only differs from `pytest.mark.with_all_tx_types` in that it does not include transaction type 3 (Blob Transaction type) on fork Cancun and after.
5757

58+
### `@pytest.mark.with_all_typed_transactions`
59+
60+
This marker is used to automatically parameterize a test with all typed transactions, including `type=0` (legacy transaction), that are valid for the fork being tested.
61+
This marker is an indirect marker that utilizes the `tx_type` values from the `pytest.mark.with_all_tx_types` marker to build default typed transactions for each `tx_type`.
62+
63+
Optional: Default typed transactions used as values for `typed_transaction` exist in `src/pytest_plugins/shared/transaction_fixtures.py` and can be overridden for the scope of
64+
the test by re-defining the appropriate `pytest.fixture` for that transaction type.
65+
66+
```python
67+
import pytest
68+
69+
from ethereum_test_tools import Account, Alloc, StateTestFiller
70+
from ethereum_test_types import Transaction
71+
72+
# Optional override for type 2 transaction
73+
@pytest.fixture
74+
def type_2_default_transaction(sender: Account):
75+
return Transaction(
76+
ty=2,
77+
sender=sender,
78+
max_fee_per_gas=0x1337,
79+
max_priority_fee_per_gas=0x1337,
80+
...
81+
)
82+
83+
# Optional override for type 4 transaction
84+
@pytest.fixture
85+
def type_4_default_transaction(sender: Account, pre: Alloc):
86+
return Transaction(
87+
ty=4,
88+
sender=sender,
89+
...,
90+
authorization_list=[
91+
AuthorizationTuple(
92+
address=Address(1234),
93+
nonce=0,
94+
chain_id=1,
95+
signer=pre.fund_eoa(),
96+
)
97+
]
98+
)
99+
100+
101+
@pytest.mark.with_all_typed_transactions
102+
@pytest.mark.valid_from("Prague")
103+
def test_something_with_all_tx_types(
104+
state_test: StateTestFiller,
105+
pre: Alloc,
106+
typed_transaction: Transaction
107+
):
108+
pass
109+
```
110+
58111
### `@pytest.mark.with_all_precompiles`
59112

60113
This marker is used to automatically parameterize a test with all precompiles that are valid for the fork being tested.

src/cli/pytest_commands/pytest_ini_files/pytest-check-eip-versions.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ addopts =
1313
-p pytest_plugins.filler.pre_alloc
1414
-p pytest_plugins.filler.filler
1515
-p pytest_plugins.shared.execute_fill
16+
-p pytest_plugins.shared.transaction_fixtures
1617
-p pytest_plugins.forks.forks
1718
-p pytest_plugins.help.help
1819
-m eip_version_check

src/cli/pytest_commands/pytest_ini_files/pytest-execute-hive.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ addopts =
1414
-p pytest_plugins.execute.rpc.hive
1515
-p pytest_plugins.execute.execute
1616
-p pytest_plugins.shared.execute_fill
17+
-p pytest_plugins.shared.transaction_fixtures
1718
-p pytest_plugins.forks.forks
1819
-p pytest_plugins.pytest_hive.pytest_hive
1920
-p pytest_plugins.help.help

src/cli/pytest_commands/pytest_ini_files/pytest-execute.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ addopts =
1414
-p pytest_plugins.execute.pre_alloc
1515
-p pytest_plugins.execute.execute
1616
-p pytest_plugins.shared.execute_fill
17+
-p pytest_plugins.shared.transaction_fixtures
1718
-p pytest_plugins.execute.rpc.remote_seed_sender
1819
-p pytest_plugins.execute.rpc.remote
1920
-p pytest_plugins.forks.forks

src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ addopts =
1515
-p pytest_plugins.filler.ported_tests
1616
-p pytest_plugins.filler.static_filler
1717
-p pytest_plugins.shared.execute_fill
18+
-p pytest_plugins.shared.transaction_fixtures
1819
-p pytest_plugins.forks.forks
1920
-p pytest_plugins.eels_resolver
2021
-p pytest_plugins.help.help

src/pytest_plugins/forks/forks.py

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,13 +257,16 @@ class CovariantDecorator(CovariantDescriptor):
257257
description: Description of the marker.
258258
fork_attribute_name: Name of the method to call on the fork to get the values.
259259
marker_parameter_names: Names of the parameters to be parametrized in the test function.
260+
indirect: Whether the parameters should be passed through fixtures (indirect
261+
parametrization).
260262
261263
"""
262264

263265
marker_name: ClassVar[str]
264266
description: ClassVar[str]
265267
fork_attribute_name: ClassVar[str]
266268
marker_parameter_names: ClassVar[List[str]]
269+
indirect: ClassVar[bool]
267270

268271
def __init__(self, metafunc: Metafunc):
269272
"""
@@ -317,6 +320,7 @@ def covariant_decorator(
317320
description: str,
318321
fork_attribute_name: str,
319322
argnames: List[str],
323+
indirect: bool = False,
320324
) -> Type[CovariantDecorator]:
321325
"""Generate a new covariant decorator subclass."""
322326
return type(
@@ -327,6 +331,7 @@ def covariant_decorator(
327331
"description": description,
328332
"fork_attribute_name": fork_attribute_name,
329333
"marker_parameter_names": argnames,
334+
"indirect": indirect,
330335
},
331336
)
332337

@@ -346,6 +351,16 @@ def covariant_decorator(
346351
fork_attribute_name="contract_creating_tx_types",
347352
argnames=["tx_type"],
348353
),
354+
covariant_decorator(
355+
marker_name="with_all_typed_transactions",
356+
description="marks a test to be parametrized with default typed transactions named "
357+
"typed_transaction",
358+
fork_attribute_name="tx_types",
359+
argnames=["typed_transaction"],
360+
# indirect means the values from `tx_types` will be passed to the
361+
# `typed_transaction` fixture which will then be used in the test
362+
indirect=True,
363+
),
349364
covariant_decorator(
350365
marker_name="with_all_precompiles",
351366
description="marks a test to be parametrized for all precompiles at parameter named"
@@ -972,10 +987,15 @@ def add_fork_covariant_parameters(
972987
metafunc: Metafunc, fork_parametrizers: List[ForkParametrizer]
973988
) -> None:
974989
"""Iterate over the fork covariant descriptors and add their values to the test function."""
990+
# Process all covariant decorators uniformly
975991
for covariant_descriptor in fork_covariant_decorators:
976-
for fork_parametrizer in fork_parametrizers:
977-
covariant_descriptor(metafunc=metafunc).add_values(fork_parametrizer=fork_parametrizer)
992+
if list(metafunc.definition.iter_markers(covariant_descriptor.marker_name)):
993+
for fork_parametrizer in fork_parametrizers:
994+
covariant_descriptor(metafunc=metafunc).add_values(
995+
fork_parametrizer=fork_parametrizer
996+
)
978997

998+
# Handle custom parametrize_by_fork markers
979999
for marker in metafunc.definition.iter_markers():
9801000
if marker.name == "parametrize_by_fork":
9811001
descriptor = CovariantDescriptor(
@@ -1029,6 +1049,16 @@ def parameters_from_fork_parametrizer_list(
10291049

10301050
def parametrize_fork(metafunc: Metafunc, fork_parametrizers: List[ForkParametrizer]) -> None:
10311051
"""Add the fork parameters to the test function."""
1032-
metafunc.parametrize(
1033-
*parameters_from_fork_parametrizer_list(fork_parametrizers), scope="function"
1034-
)
1052+
param_names, param_values = parameters_from_fork_parametrizer_list(fork_parametrizers)
1053+
1054+
# Collect all parameters that should be indirect from the decorators
1055+
indirect = []
1056+
for covariant_descriptor in fork_covariant_decorators:
1057+
if (
1058+
list(metafunc.definition.iter_markers(covariant_descriptor.marker_name))
1059+
and covariant_descriptor.indirect
1060+
):
1061+
# Add all argnames from this decorator to indirect list
1062+
indirect.extend(covariant_descriptor.marker_parameter_names)
1063+
1064+
metafunc.parametrize(param_names, param_values, scope="function", indirect=indirect)

src/pytest_plugins/forks/tests/test_covariant_markers.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,79 @@ def test_case(state_test, system_contract):
262262
None,
263263
id="with_all_system_contracts",
264264
),
265+
pytest.param(
266+
"""
267+
import pytest
268+
from ethereum_test_tools import Transaction
269+
@pytest.mark.with_all_typed_transactions
270+
@pytest.mark.valid_from("Berlin")
271+
@pytest.mark.valid_until("Berlin")
272+
@pytest.mark.state_test_only
273+
def test_case(state_test, typed_transaction):
274+
assert isinstance(typed_transaction, Transaction)
275+
assert typed_transaction.ty in [0, 1] # Berlin supports types 0 and 1
276+
""",
277+
{"passed": 2, "failed": 0, "skipped": 0, "errors": 0},
278+
None,
279+
id="with_all_typed_transactions_berlin",
280+
),
281+
pytest.param(
282+
"""
283+
import pytest
284+
from ethereum_test_tools import Transaction
285+
@pytest.mark.with_all_typed_transactions()
286+
@pytest.mark.valid_from("London")
287+
@pytest.mark.valid_until("London")
288+
@pytest.mark.state_test_only
289+
def test_case(state_test, typed_transaction, pre):
290+
assert isinstance(typed_transaction, Transaction)
291+
assert typed_transaction.ty in [0, 1, 2] # London supports types 0, 1, 2
292+
""",
293+
{"passed": 3, "failed": 0, "skipped": 0, "errors": 0},
294+
None,
295+
id="with_all_typed_transactions_london",
296+
),
297+
pytest.param(
298+
"""
299+
import pytest
300+
from ethereum_test_tools import Transaction
301+
from ethereum_test_base_types import AccessList
302+
303+
# Override the type 3 transaction fixture
304+
@pytest.fixture
305+
def type_3_default_transaction(pre):
306+
sender = pre.fund_eoa()
307+
308+
return Transaction(
309+
ty=3,
310+
sender=sender,
311+
max_fee_per_gas=10**10,
312+
max_priority_fee_per_gas=10**9,
313+
max_fee_per_blob_gas=10**8,
314+
gas_limit=300_000,
315+
data=b"\\xFF" * 50,
316+
access_list=[
317+
AccessList(address=0x1111, storage_keys=[10, 20]),
318+
],
319+
blob_versioned_hashes=[
320+
0x0111111111111111111111111111111111111111111111111111111111111111,
321+
],
322+
)
323+
324+
@pytest.mark.with_all_typed_transactions()
325+
@pytest.mark.valid_at("Cancun")
326+
@pytest.mark.state_test_only
327+
def test_case(state_test, typed_transaction, pre):
328+
assert isinstance(typed_transaction, Transaction)
329+
if typed_transaction.ty == 3:
330+
# Verify our override worked
331+
assert typed_transaction.data == b"\\xFF" * 50
332+
assert len(typed_transaction.blob_versioned_hashes) == 1
333+
""",
334+
{"passed": 4, "failed": 0, "skipped": 0, "errors": 0},
335+
None,
336+
id="with_all_typed_transactions_with_override",
337+
),
265338
pytest.param(
266339
"""
267340
import pytest

src/pytest_plugins/shared/execute_fill.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from ethereum_test_execution import BaseExecute, LabeledExecuteFormat
88
from ethereum_test_fixtures import BaseFixture, LabeledFixtureFormat
99
from ethereum_test_specs import BaseTest
10+
from ethereum_test_types import EOA, Alloc
1011
from pytest_plugins.spec_version_checker.spec_version_checker import EIPSpecTestItem
1112

1213

@@ -150,6 +151,13 @@ def __init__(self, message):
150151
)
151152

152153

154+
# Global `sender` fixture that can be overridden by tests.
155+
@pytest.fixture
156+
def sender(pre: Alloc) -> EOA:
157+
"""Fund an EOA from pre-alloc."""
158+
return pre.fund_eoa()
159+
160+
153161
def pytest_addoption(parser: pytest.Parser):
154162
"""Add command-line options to pytest."""
155163
static_filler_group = parser.getgroup("static", "Arguments defining static filler behavior")

0 commit comments

Comments
 (0)