11"""The module contains the pytest hooks for the gas benchmark values."""
22
3- import importlib .util
43import sys
4+ from importlib .util import module_from_spec , spec_from_file_location
55from pathlib import Path
66
77import pytest
@@ -50,29 +50,40 @@ def pytest_configure(config: pytest.Config) -> None:
5050 config .op_mode = OpMode .BENCHMARKING # type: ignore[attr-defined]
5151
5252
53- def _load_opcode_counts_config (config : pytest .Config ) -> dict [str , list [int ]] | None :
53+ def load_opcode_counts_config (
54+ config : pytest .Config ,
55+ ) -> dict [str , list [int ]] | None :
5456 """
5557 Load the opcode counts configuration from `tests/benchmark/configs/fixed_opcode_counts.py`.
5658
5759 Returns dictionary mapping scenario IDs to opcode counts, or None if config not found.
5860 """
59- config_path = Path (config .rootpath ) / "tests" / "benchmark" / "configs" / "fixed_opcode_counts.py"
61+ config_path = (
62+ Path (config .rootpath )
63+ / "tests"
64+ / "benchmark"
65+ / "configs"
66+ / "fixed_opcode_counts.py"
67+ )
6068
6169 if not config_path .exists ():
6270 return None
6371
6472 # Load the module dynamically
65- spec = importlib . util . spec_from_file_location ("fixed_opcode_counts" , config_path )
73+ spec = spec_from_file_location ("fixed_opcode_counts" , config_path )
6674 if spec is None or spec .loader is None :
6775 return None
6876
69- module = importlib . util . module_from_spec (spec )
77+ module = module_from_spec (spec )
7078 sys .modules ["fixed_opcode_counts" ] = module
7179 spec .loader .exec_module (module )
7280
7381 return {
74- "scenario_counts" : getattr (module , "SCENARIO_OPCODE_COUNTS" , {}),
75- "default_counts" : getattr (module , "DEFAULT_OPCODE_COUNTS" , [100 , 500 , 1000 ]),
82+ "scenario_configs" : getattr (module , "SCENARIO_CONFIGS" , {}),
83+ "default_counts" : getattr (module , "DEFAULT_OPCODE_COUNTS" , [100 ]),
84+ "get_opcode_counts" : getattr (
85+ module , "get_opcode_counts_for_scenario" , None
86+ ),
7687 }
7788
7889
@@ -88,7 +99,7 @@ def pytest_collection_modifyitems(
8899
89100 # Load config data if flag provided without value (empty string)
90101 if fixed_opcode_count == "" :
91- config_data = _load_opcode_counts_config (config )
102+ config_data = load_opcode_counts_config (config )
92103 if config_data :
93104 config ._opcode_counts_config = config_data # type: ignore[attr-defined]
94105
@@ -161,14 +172,34 @@ def pytest_generate_tests(metafunc: pytest.Metafunc) -> None:
161172 ]
162173 elif fixed_opcode_counts_cli == "" :
163174 # Flag provided without value - load from config file
175+ # Check if config data was already loaded in pytest_collection_modifyitems
164176 config_data = getattr (
165177 metafunc .config , "_opcode_counts_config" , None
166178 )
179+
180+ # If not loaded yet (pytest_generate_tests runs first), load it now
181+ if config_data is None :
182+ config_data = load_opcode_counts_config (metafunc .config )
183+ if config_data :
184+ metafunc .config ._opcode_counts_config = config_data # type: ignore[attr-defined]
185+
167186 if config_data :
168- default_counts = config_data .get (
169- "default_counts" , [100 ] # Default to 100k for all.
170- )
171- opcode_counts_to_use = default_counts
187+ # Use the config's lookup function to get opcode counts
188+ test_name = metafunc .function .__name__
189+ get_counts_fn = config_data .get ("get_opcode_counts" )
190+
191+ if get_counts_fn :
192+ # At this stage, we only have the test name, not full parametrized IDs
193+ # The regex patterns in the config match against test_name
194+ # e.g., "test_selfbalance.*" will match "test_selfbalance"
195+ opcode_counts_to_use = get_counts_fn (
196+ test_name , test_name
197+ )
198+ else :
199+ # Fallback to default if function not available
200+ opcode_counts_to_use = config_data .get (
201+ "default_counts" , [100 ]
202+ )
172203
173204 # Parametrize if we have counts to use
174205 if opcode_counts_to_use :
0 commit comments