diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/execute.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/execute.py index 9a15a9c3ecc..f5c567627bb 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/execute.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/execute.py @@ -851,13 +851,10 @@ def pytest_collection_modifyitems( if isinstance(item, EIPSpecTestItem): continue params: Dict[str, Any] = item.callspec.params # type: ignore - if ( - "parametrized_fork" not in params - or params["parametrized_fork"] is None - ): + if "fork" not in params or params["fork"] is None: items_for_removal.append(i) continue - fork: Fork | TransitionFork = params["parametrized_fork"] + fork: Fork | TransitionFork = params["fork"] spec_type, execute_format = get_spec_format_for_item(params) assert issubclass(execute_format, BaseExecute) markers = list(item.iter_markers()) diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/filler.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/filler.py index 1b1bdb1d7b2..5a733c09ad5 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/filler.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/filler.py @@ -1922,14 +1922,10 @@ def pytest_collection_modifyitems( params = item.callspec.params elif hasattr(item, "params"): params = item.params - if ( - not params - or "parametrized_fork" not in params - or params["parametrized_fork"] is None - ): + if not params or "fork" not in params or params["fork"] is None: items_for_removal.append(i) continue - fork: Fork | TransitionFork = params["parametrized_fork"] + fork: Fork | TransitionFork = params["fork"] spec_type, fixture_format = get_spec_format_for_item(params) if isinstance(fixture_format, NotSetType): items_for_removal.append(i) diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/gen_test_doc/gen_test_doc.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/gen_test_doc/gen_test_doc.py index 88a0e586066..f5eab27ac65 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/gen_test_doc/gen_test_doc.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/gen_test_doc/gen_test_doc.py @@ -446,7 +446,7 @@ def create_function_page_props( ) for value in values ] - fork = item.callspec.params.get("parametrized_fork").name() # type: ignore + fork = item.callspec.params.get("fork").name() # type: ignore test_type = get_test_function_test_type(item) test_type_value = item.callspec.params.get(test_type) fixture_type = test_type_value.format_name # type: ignore diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/static_filler.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/static_filler.py index c6d4ea6ecf5..08b2195410f 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/static_filler.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/static_filler.py @@ -275,7 +275,7 @@ def collect(self: "FillerFile") -> Generator["FillerTestItem", None, None]: ps_id = fixture_format_parameter_set.id test_id = f"fork_{fork.name()}-{ps_id}" if "fork" in func_parameters: - params["parametrized_fork"] = fork + params["fork"] = fork if "pre" in func_parameters: fixturenames.append("pre") if "request" in func_parameters: diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/forks.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/forks.py index 6f1bb468a18..2dc7336f6e8 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/forks.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/forks.py @@ -118,7 +118,7 @@ def __init__( marks = [] self.fork_covariant_parameters = [ ForkCovariantParameter( - names=["parametrized_fork"], + names=["fork"], values=[ pytest.param( fork, @@ -671,7 +671,7 @@ def pytest_report_header(config: pytest.Config, start_path: Any) -> List[str]: @pytest.fixture(autouse=True) -def parametrized_fork(request: pytest.FixtureRequest) -> None: +def fork(request: pytest.FixtureRequest) -> None: """Parametrize test cases by fork.""" pass @@ -1234,9 +1234,7 @@ def pytest_generate_tests(metafunc: pytest.Metafunc) -> None: ], ) ] - metafunc.parametrize( - "parametrized_fork", pytest_params, scope="function" - ) + metafunc.parametrize("fork", pytest_params, scope="function") return # Get the intersection between the test's validity marker and the current @@ -1245,7 +1243,7 @@ def pytest_generate_tests(metafunc: pytest.Metafunc) -> None: test_fork_set & metafunc.config.selected_fork_set # type: ignore ) - if "parametrized_fork" not in metafunc.fixturenames: + if "fork" not in metafunc.fixturenames: return unsupported_forks: Set[Fork | TransitionFork] = ( @@ -1268,9 +1266,7 @@ def pytest_generate_tests(metafunc: pytest.Metafunc) -> None: ], ) ] - metafunc.parametrize( - "parametrized_fork", pytest_params, scope="function" - ) + metafunc.parametrize("fork", pytest_params, scope="function") else: pytest_params = [] for fork in sorted(intersection_set): @@ -1574,7 +1570,7 @@ def pytest_collection_modifyitems( continue # --- validity markers --- - fork = params.get("parametrized_fork") + fork = params.get("fork") if fork is None: continue diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/tests/test_fork_parametrizer_types.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/tests/test_fork_parametrizer_types.py index 381eb4712fd..cb1aa6da1f3 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/tests/test_fork_parametrizer_types.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/tests/test_fork_parametrizer_types.py @@ -19,7 +19,7 @@ [ pytest.param( [ForkParametrizer(fork=Frontier)], - ["parametrized_fork"], + ["fork"], [pytest.param(Frontier)], id="only_fork", ), @@ -34,7 +34,7 @@ ], ) ], - ["parametrized_fork", "some_value"], + ["fork", "some_value"], [pytest.param(Frontier, 1)], id="fork_with_single_covariant_parameter", ), @@ -50,7 +50,7 @@ ], ) ], - ["parametrized_fork", "some_value"], + ["fork", "some_value"], [pytest.param(Frontier, 1), pytest.param(Frontier, 2)], id="fork_with_single_covariant_parameter_multiple_values", ), @@ -69,7 +69,7 @@ ], ) ], - ["parametrized_fork", "some_value"], + ["fork", "some_value"], [ pytest.param(Frontier, 1, marks=[pytest.mark.some_mark]), pytest.param(Frontier, 2), @@ -90,7 +90,7 @@ ], ) ], - ["parametrized_fork", "some_value", "another_value"], + ["fork", "some_value", "another_value"], [pytest.param(Frontier, 1, 2)], id="fork_with_multiple_covariant_parameters", ), @@ -109,7 +109,7 @@ ], ) ], - ["parametrized_fork", "some_value", "another_value"], + ["fork", "some_value", "another_value"], [pytest.param(Frontier, 1, 2), pytest.param(Frontier, 1, 3)], id="fork_with_multiple_covariant_parameters_multiple_values", ), @@ -128,7 +128,7 @@ ], ) ], - ["parametrized_fork", "some_value", "another_value"], + ["fork", "some_value", "another_value"], [pytest.param(Frontier, 1, "a"), pytest.param(Frontier, 2, "b")], id="fork_with_single_multi_value_covariant_parameter_multiple_values", ), @@ -155,7 +155,7 @@ ) ], [ - "parametrized_fork", + "fork", "some_value", "another_value", "yet_another_value", @@ -191,12 +191,7 @@ ], ) ], - [ - "parametrized_fork", - "shared_value", - "different_value_1", - "different_value_2", - ], + ["fork", "shared_value", "different_value_1", "different_value_2"], [ pytest.param(Frontier, 1, "a", "x"), pytest.param(Frontier, 2, "b", "y"), diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/shared/benchmarking.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/shared/benchmarking.py index ed98551a10e..2a47ed80365 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/shared/benchmarking.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/shared/benchmarking.py @@ -553,26 +553,16 @@ def _is_benchmark_test(request: pytest.FixtureRequest) -> bool: @pytest.fixture -def env_gas_limit(request: pytest.FixtureRequest) -> int: +def genesis_environment(request: pytest.FixtureRequest) -> Environment: """Return an Environment with appropriate gas limit.""" if _is_benchmark_test(request): - return BENCHMARKING_MAX_GAS - return EnvironmentDefaults.gas_limit - - -@pytest.fixture -def genesis_environment( - request: pytest.FixtureRequest, env_gas_limit: int -) -> Environment: - """Return an Environment with appropriate gas limit.""" - if _is_benchmark_test(request): - return Environment(gas_limit=env_gas_limit) + return Environment(gas_limit=BENCHMARKING_MAX_GAS) return Environment() @pytest.fixture -def env(request: pytest.FixtureRequest, env_gas_limit: int) -> Environment: +def env(request: pytest.FixtureRequest) -> Environment: """Return an Environment with appropriate gas limit.""" if _is_benchmark_test(request): - return Environment(gas_limit=env_gas_limit) + return Environment(gas_limit=BENCHMARKING_MAX_GAS) return Environment() diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/shared/execute_fill.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/shared/execute_fill.py index 8b33474dfc4..d827d96927a 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/shared/execute_fill.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/shared/execute_fill.py @@ -2,10 +2,8 @@ Shared pytest fixtures and hooks for EEST generation modes (fill and execute). """ -from __future__ import annotations - from pathlib import Path -from typing import TYPE_CHECKING, Dict, List, Tuple +from typing import Dict, List, Tuple import pytest from pytest import StashKey @@ -17,20 +15,11 @@ LabeledExecuteFormat, ) from execution_testing.fixtures import BaseFixture, LabeledFixtureFormat - -if TYPE_CHECKING: - from execution_testing.forks import Fork, TransitionFork -import sys - from execution_testing.logging import get_logger from execution_testing.rpc import EthRPC from execution_testing.specs import BaseTest from execution_testing.specs.base import OpMode -from execution_testing.test_types import ( - EOA, - Alloc, - ChainConfig, -) +from execution_testing.test_types import EOA, Alloc, ChainConfig from ..shared.address_stubs import AddressStubs, StubEOA from ..shared.helpers import get_rpc_endpoint @@ -321,58 +310,9 @@ def pytest_make_parametrize_id( readable test ids for the generated tests. """ del config - if argname == "parametrized_fork": - return f"fork_{val}" return f"{argname}_{val}" -@pytest.fixture(scope="function") -def fork( - parametrized_fork: Fork | TransitionFork, - monkeypatch: pytest.MonkeyPatch, - env_gas_limit: int, -) -> Fork | TransitionFork: - """ - Return a per-test fork variant whose ``_env_gas_limit`` tracks the - ``Environment.gas_limit`` used by the test. - """ - fork_variant = parametrized_fork.with_env_gas_limit(env_gas_limit) - - # Now we monkey-patch the `Environment` class with one that is aware of - # the fork that the test is using, and will update its `_env_gas_limit` - # automatically. - # TODO: This should not be necessary, we should treat the `env` object the - # same way we do `pre` and force it to be a singleton in the test's - # context. - from execution_testing.test_types.block_types import ( - Environment as OriginalEnvironment, - ) - - class _ForkAwareEnvironment(OriginalEnvironment): - """Transparently syncs ``gas_limit`` back to the fork variant.""" - - def model_post_init(self, __context: object) -> None: - super().model_post_init(__context) - fork_variant._env_gas_limit = int(self.gas_limit) - - def __setattr__(self, name: str, value: object) -> None: - super().__setattr__(name, value) - if name == "gas_limit": - fork_variant._env_gas_limit = int(self.gas_limit) - - # Replace Environment in every module that imported the original class - # so that both `Environment(...)` in test code and in conftest fixtures - # create _ForkAwareEnvironment instances. - for mod in list(sys.modules.values()): - try: - if getattr(mod, "Environment", None) is OriginalEnvironment: - monkeypatch.setattr(mod, "Environment", _ForkAwareEnvironment) - except Exception: - continue - - return fork_variant - - SPEC_TYPES_PARAMETERS: List[str] = list(BaseTest.spec_types.keys()) diff --git a/packages/testing/src/execution_testing/forks/base_fork.py b/packages/testing/src/execution_testing/forks/base_fork.py index afdc3ccfbc0..c074c3da840 100644 --- a/packages/testing/src/execution_testing/forks/base_fork.py +++ b/packages/testing/src/execution_testing/forks/base_fork.py @@ -184,7 +184,7 @@ def __repr__(cls) -> str: return cls.name() @staticmethod - def _maybe_transitioned(fork_cls: type) -> type: + def _maybe_transitioned(fork_cls: "BaseForkMeta") -> "BaseForkMeta": """ Return the transitioned fork, if a transition fork, otherwise return `fork_cls`. @@ -198,54 +198,35 @@ def _maybe_transitioned(fork_cls: type) -> type: @staticmethod def _is_subclass_of(a: "BaseForkMeta", b: "BaseForkMeta") -> bool: """ - Check if `a` is a subclass of `b`, taking fork transitions and - variants (created by `with_env_gas_limit`) into account. + Check if `a` is a subclass of `b`, taking fork transitions into + account. """ - # Resolve variants to canonical identity so comparisons between - # a variant and a canonical descendant fork work as expected. - a_id: type = BaseForkMeta._identity(a) - b_id: type = BaseForkMeta._identity(b) - a_id = BaseForkMeta._maybe_transitioned(a_id) - b_id = BaseForkMeta._maybe_transitioned(b_id) - return issubclass(a_id, b_id) - - @staticmethod - def _identity(fork_cls: type) -> type: - """Return the canonical fork class, resolving variants.""" - base = getattr(fork_cls, "_base_fork", None) - return base if base is not None else fork_cls - - def __eq__(cls, other: object) -> bool: - """Compare fork identity, treating variants as equal to parents.""" - if not isinstance(other, BaseForkMeta): - return NotImplemented - return BaseForkMeta._identity(cls) is BaseForkMeta._identity(other) - - def __hash__(cls) -> int: - """Hash by canonical fork identity.""" - return id(BaseForkMeta._identity(cls)) + a = BaseForkMeta._maybe_transitioned(a) + b = BaseForkMeta._maybe_transitioned(b) + return issubclass(a, b) def __gt__(cls, other: "BaseForkMeta") -> bool: """Compare if a fork is newer than some other fork (cls > other).""" - return cls != other and BaseForkMeta._is_subclass_of(cls, other) + return cls is not other and BaseForkMeta._is_subclass_of(cls, other) def __ge__(cls, other: "BaseForkMeta") -> bool: """ Compare if a fork is newer than or equal to some other fork (cls >= other). """ - return cls == other or BaseForkMeta._is_subclass_of(cls, other) + return cls is other or BaseForkMeta._is_subclass_of(cls, other) def __lt__(cls, other: "BaseForkMeta") -> bool: """Compare if a fork is older than some other fork (cls < other).""" - return cls != other and BaseForkMeta._is_subclass_of(other, cls) + # "Older" means other is a subclass of cls, but not the same. + return cls is not other and BaseForkMeta._is_subclass_of(other, cls) def __le__(cls, other: "BaseForkMeta") -> bool: """ Compare if a fork is older than or equal to some other fork (cls <= other). """ - return cls == other or BaseForkMeta._is_subclass_of(other, cls) + return cls is other or BaseForkMeta._is_subclass_of(other, cls) class BaseFork(ForkOpcodeInterface, metaclass=BaseForkMeta): @@ -265,10 +246,6 @@ class BaseFork(ForkOpcodeInterface, metaclass=BaseForkMeta): _ruleset_name: ClassVar[Optional[str]] = None _fork_by_timestamp: ClassVar[bool] = False _blob_constants: ClassVar[Dict[str, int]] = {} - - # Environment overrides (set on variants created by with_env_gas_limit) - _base_fork: ClassVar[Optional[Type["BaseFork"]]] = None - _env_gas_limit: ClassVar[int] = 0 _deployed: ClassVar[bool] = True _enabled_eips: ClassVar[Set[int]] = set() _enabling_forks: ClassVar[Set[Type["BaseFork"]]] = set() @@ -1132,24 +1109,6 @@ def children(cls) -> Set[Type["BaseFork"]]: """Return the children forks.""" return set(cls._children) - @classmethod - def with_env_gas_limit(cls, env_gas_limit: int) -> Type["BaseFork"]: - """Return a new fork class with the specified environment gas limit.""" - new_cls = type(cls.__name__, (cls,), {}) - # __init_subclass__ resets per-class overrides; restore from parent. - new_cls._env_gas_limit = env_gas_limit # type: ignore[attr-defined] - new_cls._base_fork = cls._base_fork or cls # type: ignore[attr-defined] - new_cls._transition_tool_name = ( # type: ignore[attr-defined] - cls._transition_tool_name - ) - new_cls._solc_name = cls._solc_name # type: ignore[attr-defined] - new_cls._ignore = cls._ignore # type: ignore[attr-defined] - new_cls._bpo_fork = cls._bpo_fork # type: ignore[attr-defined] - new_cls._ruleset_name = cls._ruleset_name # type: ignore[attr-defined] - # Prevent the variant from appearing in fork traversals. - cls._children.discard(new_cls) - return new_cls - @classmethod @abstractmethod def build_default_block_header( diff --git a/packages/testing/src/execution_testing/forks/tests/test_forks.py b/packages/testing/src/execution_testing/forks/tests/test_forks.py index d82d31e5c4a..8d9cec7882c 100644 --- a/packages/testing/src/execution_testing/forks/tests/test_forks.py +++ b/packages/testing/src/execution_testing/forks/tests/test_forks.py @@ -24,7 +24,6 @@ Paris, Prague, Shanghai, - SpuriousDragon, ) from ..forks.transition import ( BerlinToLondonAt5, @@ -732,54 +731,3 @@ def test_eips() -> None: # noqa: D103 assert not Paris.is_eip_enabled(3675, 3855) assert not Paris.is_eip_enabled(3855, 3675) assert Shanghai.is_eip_enabled(3855) - - -def test_fork_variant_ordering() -> None: - """ - Variants from `with_env_gas_limit` must compare consistently with - their canonical parent: equal to the parent, ordered identically - against other canonical forks. - """ - variant = London.with_env_gas_limit(30_000_000) - - assert variant == London - assert hash(variant) == hash(London) - - assert variant > SpuriousDragon - assert variant >= SpuriousDragon - assert variant < Cancun - assert variant <= Cancun - - assert not (variant > London) - assert not (variant < London) - assert variant >= London - assert variant <= London - - -def test_transition_fork_variant_equality() -> None: - """ - Variants of a transition fork created via `with_env_gas_limit` must - compare equal to their canonical parent and to each other, even when - different gas limits are used. Distinct canonical transition forks - must remain unequal. - """ - canonical = CancunToPragueAtTime15k - variant_a = canonical.with_env_gas_limit(30_000_000) - variant_b = canonical.with_env_gas_limit(45_000_000) - variant_c = canonical.with_env_gas_limit(30_000_000) - - assert variant_a is not canonical - assert variant_a is not variant_b - assert variant_a is not variant_c - - assert variant_a == canonical - assert variant_b == canonical - assert variant_a == variant_b - assert variant_a == variant_c - - assert hash(variant_a) == hash(canonical) - assert hash(variant_b) == hash(canonical) - assert hash(variant_c) == hash(canonical) - - assert canonical != PragueToOsakaAtTime15k - assert variant_a != PragueToOsakaAtTime15k diff --git a/packages/testing/src/execution_testing/forks/transition_base_fork.py b/packages/testing/src/execution_testing/forks/transition_base_fork.py index 482b3c877ff..3dca0cb1d31 100644 --- a/packages/testing/src/execution_testing/forks/transition_base_fork.py +++ b/packages/testing/src/execution_testing/forks/transition_base_fork.py @@ -1,8 +1,8 @@ """Base objects used to define transition forks.""" -from typing import Any, Callable, ClassVar, Dict, Optional, Type +from typing import Any, Callable, ClassVar, Dict, Type -from .base_fork import BaseFork, BaseForkMeta +from .base_fork import BaseFork class TransitionBaseMetaClass(type): @@ -15,19 +15,6 @@ def name(cls) -> str: """ raise Exception("Not implemented") - def __eq__(cls, other: object) -> bool: - """ - Compare transition fork identity, treating variants created by - `with_env_gas_limit` as equal to their canonical parent. - """ - if not isinstance(other, type): - return NotImplemented - return BaseForkMeta._identity(cls) is BaseForkMeta._identity(other) - - def __hash__(cls) -> int: - """Hash by canonical transition fork identity.""" - return id(BaseForkMeta._identity(cls)) - def transitions_to(cls) -> Type[BaseFork]: """ Return fork where the transition ends. @@ -88,8 +75,6 @@ class TransitionBaseClass(metaclass=TransitionBaseMetaClass): at_block: ClassVar[int] = 0 at_timestamp: ClassVar[int] = 0 _ignore: ClassVar[bool] = False - _env_gas_limit: ClassVar[int] = 0 - _base_fork: ClassVar[Optional[Type["TransitionBaseClass"]]] = None @classmethod def fork_at( @@ -121,19 +106,6 @@ def ruleset(cls) -> Dict[str, int]: """ raise Exception("Not implemented") - @classmethod - def with_env_gas_limit( - cls, env_gas_limit: int - ) -> Type["TransitionBaseClass"]: - """ - Return a new transition fork class with the specified environment - gas limit. - """ - new_cls = type(cls.__name__, (cls,), {}) - new_cls._env_gas_limit = env_gas_limit # type: ignore[attr-defined] - new_cls._base_fork = cls._base_fork or cls # type: ignore[attr-defined] - return new_cls - def transition_fork( to_fork: Type[BaseFork], @@ -162,30 +134,23 @@ class NewTransitionClass( ): _ignore = ignore - @classmethod - def _propagate_env(cls, fork: Type[BaseFork]) -> Type[BaseFork]: - if cls._env_gas_limit: - return fork.with_env_gas_limit(cls._env_gas_limit) - return fork - @classmethod def transitions_to(cls) -> Type[BaseFork]: - return cls._propagate_env(to_fork) + return to_fork @classmethod def transitions_from(cls) -> Type[BaseFork]: - return cls._propagate_env(from_fork) + return from_fork @classmethod def fork_at( cls, *, block_number: int = 0, timestamp: int = 0 ) -> Type[BaseFork]: - fork = ( + return ( to_fork if block_number >= at_block and timestamp >= at_timestamp else from_fork ) - return cls._propagate_env(fork) @classmethod def name(cls) -> str: