Skip to content

Commit 1c1e00a

Browse files
committed
refactor(consume): split base functionality out to the base plugin
These are fixtures that can also be shared by multi-client architecture simulators.
1 parent def0da6 commit 1c1e00a

File tree

4 files changed

+90
-79
lines changed

4 files changed

+90
-79
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"""Common pytest fixtures for the Hive simulators."""
2+
3+
from pathlib import Path
4+
from typing import Dict, Literal
5+
6+
import pytest
7+
from hive.client import Client
8+
9+
from ethereum_test_fixtures import (
10+
BaseFixture,
11+
)
12+
from ethereum_test_fixtures.consume import TestCaseIndexFile, TestCaseStream
13+
from ethereum_test_fixtures.file import Fixtures
14+
from ethereum_test_rpc import EthRPC
15+
from pytest_plugins.consume.consume import FixturesSource
16+
17+
18+
@pytest.fixture(scope="function")
19+
def eth_rpc(client: Client) -> EthRPC:
20+
"""Initialize ethereum RPC client for the execution client under test."""
21+
return EthRPC(f"http://{client.ip}:8545")
22+
23+
24+
@pytest.fixture(scope="function")
25+
def check_live_port(test_suite_name: str) -> Literal[8545, 8551]:
26+
"""Port used by hive to check for liveness of the client."""
27+
if test_suite_name == "eest/consume-rlp":
28+
return 8545
29+
elif test_suite_name == "eest/consume-engine":
30+
return 8551
31+
raise ValueError(
32+
f"Unexpected test suite name '{test_suite_name}' while setting HIVE_CHECK_LIVE_PORT."
33+
)
34+
35+
36+
class FixturesDict(Dict[Path, Fixtures]):
37+
"""
38+
A dictionary caches loaded fixture files to avoid reloading the same file
39+
multiple times.
40+
"""
41+
42+
def __init__(self) -> None:
43+
"""Initialize the dictionary that caches loaded fixture files."""
44+
self._fixtures: Dict[Path, Fixtures] = {}
45+
46+
def __getitem__(self, key: Path) -> Fixtures:
47+
"""Return the fixtures from the index file, if not found, load from disk."""
48+
assert key.is_file(), f"Expected a file path, got '{key}'"
49+
if key not in self._fixtures:
50+
self._fixtures[key] = Fixtures.model_validate_json(key.read_text())
51+
return self._fixtures[key]
52+
53+
54+
@pytest.fixture(scope="session")
55+
def fixture_file_loader() -> Dict[Path, Fixtures]:
56+
"""Return a singleton dictionary that caches loaded fixture files used in all tests."""
57+
return FixturesDict()
58+
59+
60+
@pytest.fixture(scope="function")
61+
def fixture(
62+
fixtures_source: FixturesSource,
63+
fixture_file_loader: Dict[Path, Fixtures],
64+
test_case: TestCaseIndexFile | TestCaseStream,
65+
) -> BaseFixture:
66+
"""
67+
Load the fixture from a file or from stream in any of the supported
68+
fixture formats.
69+
70+
The fixture is either already available within the test case (if consume
71+
is taking input on stdin) or loaded from the fixture json file if taking
72+
input from disk (fixture directory with index file).
73+
"""
74+
fixture: BaseFixture
75+
if fixtures_source.is_stdin:
76+
assert isinstance(test_case, TestCaseStream), "Expected a stream test case"
77+
fixture = test_case.fixture
78+
else:
79+
assert isinstance(test_case, TestCaseIndexFile), "Expected an index file test case"
80+
fixtures_file_path = fixtures_source.path / test_case.json_path
81+
fixtures: Fixtures = fixture_file_loader[fixtures_file_path]
82+
fixture = fixtures[test_case.id]
83+
assert isinstance(fixture, test_case.format), (
84+
f"Expected a {test_case.format.format_name} test fixture"
85+
)
86+
return fixture

src/pytest_plugins/consume/simulators/engine/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from ethereum_test_rpc import EngineRPC
1616

1717
pytest_plugins = (
18+
"pytest_plugins.consume.simulators.base",
1819
"pytest_plugins.consume.simulators.single_test_client",
1920
"pytest_plugins.consume.simulators.test_case_description",
2021
"pytest_plugins.consume.simulators.timing_data",

src/pytest_plugins/consume/simulators/rlp/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
TestCase = TestCaseIndexFile | TestCaseStream
1313

1414
pytest_plugins = (
15+
"pytest_plugins.consume.simulators.base",
1516
"pytest_plugins.consume.simulators.single_test_client",
1617
"pytest_plugins.consume.simulators.test_case_description",
1718
"pytest_plugins.consume.simulators.timing_data",
Lines changed: 2 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
1-
"""Common pytest fixtures for the RLP and Engine simulators."""
1+
"""Common pytest fixtures for simulators with single-test client architecture."""
22

33
import io
44
import json
55
import logging
6-
from pathlib import Path
7-
from typing import Dict, Generator, Literal, cast
6+
from typing import Generator, Literal, cast
87

98
import pytest
109
from hive.client import Client, ClientType
1110
from hive.testing import HiveTest
1211

1312
from ethereum_test_base_types import Number, to_json
1413
from ethereum_test_fixtures import (
15-
BaseFixture,
1614
BlockchainFixtureCommon,
1715
)
18-
from ethereum_test_fixtures.consume import TestCaseIndexFile, TestCaseStream
19-
from ethereum_test_fixtures.file import Fixtures
20-
from ethereum_test_rpc import EthRPC
21-
from pytest_plugins.consume.consume import FixturesSource
2216
from pytest_plugins.consume.simulators.helpers.ruleset import (
2317
ruleset, # TODO: generate dynamically
2418
)
@@ -28,12 +22,6 @@
2822
logger = logging.getLogger(__name__)
2923

3024

31-
@pytest.fixture(scope="function")
32-
def eth_rpc(client: Client) -> EthRPC:
33-
"""Initialize ethereum RPC client for the execution client under test."""
34-
return EthRPC(f"http://{client.ip}:8545")
35-
36-
3725
@pytest.fixture(scope="function")
3826
def client_genesis(fixture: BlockchainFixtureCommon) -> dict:
3927
"""Convert the fixture genesis block header and pre-state to a client genesis state."""
@@ -44,18 +32,6 @@ def client_genesis(fixture: BlockchainFixtureCommon) -> dict:
4432
return genesis
4533

4634

47-
@pytest.fixture(scope="function")
48-
def check_live_port(test_suite_name: str) -> Literal[8545, 8551]:
49-
"""Port used by hive to check for liveness of the client."""
50-
if test_suite_name == "eest/consume-rlp":
51-
return 8545
52-
elif test_suite_name == "eest/consume-engine":
53-
return 8551
54-
raise ValueError(
55-
f"Unexpected test suite name '{test_suite_name}' while setting HIVE_CHECK_LIVE_PORT."
56-
)
57-
58-
5935
@pytest.fixture(scope="function")
6036
def environment(
6137
fixture: BlockchainFixtureCommon,
@@ -105,56 +81,3 @@ def client(
10581
with total_timing_data.time("Stop client"):
10682
client.stop()
10783
logger.info(f"Client ({client_type.name}) stopped!")
108-
109-
110-
class FixturesDict(Dict[Path, Fixtures]):
111-
"""
112-
A dictionary caches loaded fixture files to avoid reloading the same file
113-
multiple times.
114-
"""
115-
116-
def __init__(self) -> None:
117-
"""Initialize the dictionary that caches loaded fixture files."""
118-
self._fixtures: Dict[Path, Fixtures] = {}
119-
120-
def __getitem__(self, key: Path) -> Fixtures:
121-
"""Return the fixtures from the index file, if not found, load from disk."""
122-
assert key.is_file(), f"Expected a file path, got '{key}'"
123-
if key not in self._fixtures:
124-
self._fixtures[key] = Fixtures.model_validate_json(key.read_text())
125-
return self._fixtures[key]
126-
127-
128-
@pytest.fixture(scope="session")
129-
def fixture_file_loader() -> Dict[Path, Fixtures]:
130-
"""Return a singleton dictionary that caches loaded fixture files used in all tests."""
131-
return FixturesDict()
132-
133-
134-
@pytest.fixture(scope="function")
135-
def fixture(
136-
fixtures_source: FixturesSource,
137-
fixture_file_loader: Dict[Path, Fixtures],
138-
test_case: TestCaseIndexFile | TestCaseStream,
139-
) -> BaseFixture:
140-
"""
141-
Load the fixture from a file or from stream in any of the supported
142-
fixture formats.
143-
144-
The fixture is either already available within the test case (if consume
145-
is taking input on stdin) or loaded from the fixture json file if taking
146-
input from disk (fixture directory with index file).
147-
"""
148-
fixture: BaseFixture
149-
if fixtures_source.is_stdin:
150-
assert isinstance(test_case, TestCaseStream), "Expected a stream test case"
151-
fixture = test_case.fixture
152-
else:
153-
assert isinstance(test_case, TestCaseIndexFile), "Expected an index file test case"
154-
fixtures_file_path = fixtures_source.path / test_case.json_path
155-
fixtures: Fixtures = fixture_file_loader[fixtures_file_path]
156-
fixture = fixtures[test_case.id]
157-
assert isinstance(fixture, test_case.format), (
158-
f"Expected a {test_case.format.format_name} test fixture"
159-
)
160-
return fixture

0 commit comments

Comments
 (0)