11"""Ethereum benchmark test spec definition and filler."""
22
33from abc import ABC , abstractmethod
4- from contextlib import contextmanager
5- from contextvars import ContextVar
64from dataclasses import dataclass , field
7- from enum import Enum
8- from typing import Any , Callable , ClassVar , Dict , Generator , List , Optional , Sequence , Type
5+ from typing import Callable , ClassVar , Dict , Generator , List , Sequence , Type
96
107import pytest
11- from pydantic import ConfigDict , Field , GetCoreSchemaHandler
12- from pydantic_core .core_schema import (
13- PlainValidatorFunctionSchema ,
14- no_info_plain_validator_function ,
15- to_string_ser_schema ,
16- )
8+ from pydantic import ConfigDict , Field
179
1810from ethereum_clis import TransitionTool
1911from ethereum_test_base_types import HexNumber
@@ -83,88 +75,6 @@ def _validate_code_size(self, code: Bytecode, fork: Fork) -> None:
8375 )
8476
8577
86- class BenchmarkPhase (Enum ):
87- """Phases of a benchmark test."""
88-
89- SETUP = "setup"
90- EXECUTION = "execution"
91-
92-
93- _current_phase : ContextVar [Optional [BenchmarkPhase ]] = ContextVar ("benchmark_phase" , default = None )
94-
95-
96- class BenchmarkManager :
97- """Context manager for managing benchmark test phases."""
98-
99- def __init__ (self ):
100- """Initialize the BenchmarkManager with empty transaction and block lists."""
101- self .setup_transactions : List [Transaction ] = []
102- self .setup_blocks : List [Block ] = []
103- self .execution_transactions : List [Transaction ] = []
104- self .execution_blocks : List [Block ] = []
105-
106- @contextmanager
107- def setup (self ):
108- """Context manager for the setup phase of a benchmark test."""
109- token = _current_phase .set (BenchmarkPhase .SETUP )
110- try :
111- yield self
112- finally :
113- _current_phase .reset (token )
114-
115- @contextmanager
116- def execution (self ):
117- """Context manager for the execution phase of a benchmark test."""
118- token = _current_phase .set (BenchmarkPhase .EXECUTION )
119- try :
120- yield self
121- finally :
122- _current_phase .reset (token )
123-
124- def add_transaction (self , tx : Transaction ):
125- """Add a transaction to the current phase."""
126- current_phase = _current_phase .get ()
127- if current_phase == BenchmarkPhase .SETUP :
128- self .setup_transactions .append (tx )
129- elif current_phase == BenchmarkPhase .EXECUTION :
130- self .execution_transactions .append (tx )
131- else :
132- self .setup_transactions .append (tx )
133-
134- def add_block (self , block : Block ):
135- """Add a block to the current phase."""
136- current_phase = _current_phase .get ()
137- if current_phase == BenchmarkPhase .SETUP :
138- self .setup_blocks .append (block )
139- elif current_phase == BenchmarkPhase .EXECUTION :
140- self .execution_blocks .append (block )
141- else :
142- self .setup_blocks .append (block )
143-
144- def get_current_phase (self ) -> Optional [BenchmarkPhase ]:
145- """Get the current benchmark phase."""
146- return _current_phase .get ()
147-
148- @classmethod
149- def __get_pydantic_core_schema__ (
150- cls , source_type : Any , handler : GetCoreSchemaHandler
151- ) -> PlainValidatorFunctionSchema :
152- """Provide Pydantic core schema for BenchmarkManager serialization and validation."""
153-
154- def validate_benchmark_manager (value ):
155- if isinstance (value , cls ):
156- return value
157- if value is None :
158- return None
159- # If value is passed as arguments, create new instance with no args
160- return cls ()
161-
162- return no_info_plain_validator_function (
163- validate_benchmark_manager ,
164- serialization = to_string_ser_schema (),
165- )
166-
167-
16878class BenchmarkTest (BaseTest ):
16979 """Test type designed specifically for benchmark test cases."""
17080
@@ -180,7 +90,6 @@ class BenchmarkTest(BaseTest):
18090 env : Environment = Field (default_factory = Environment )
18191 expected_benchmark_gas_used : int | None = None
18292 gas_benchmark_value : int = Field (default_factory = lambda : int (Environment ().gas_limit ))
183- benchmark_manager : BenchmarkManager | None = None
18493 code_generator : BenchmarkCodeGenerator | None = None
18594
18695 supported_fixture_formats : ClassVar [Sequence [FixtureFormat | LabeledFixtureFormat ]] = [
@@ -274,33 +183,6 @@ def generate_blockchain_test(self, fork: Fork) -> BlockchainTest:
274183 blocks = generated_blocks ,
275184 )
276185
277- elif self .benchmark_manager is not None :
278- all_blocks = []
279- gas_limit = fork .transaction_gas_limit_cap () or self .gas_benchmark_value
280-
281- if self .benchmark_manager .setup_blocks :
282- all_blocks .extend (self .benchmark_manager .setup_blocks )
283- elif self .benchmark_manager .setup_transactions :
284- setup_txs = []
285- for tx in self .benchmark_manager .setup_transactions :
286- setup_txs .extend (self .split_transaction (tx , gas_limit ))
287- all_blocks .append (Block (txs = setup_txs ))
288-
289- if self .benchmark_manager .execution_blocks :
290- all_blocks .extend (self .benchmark_manager .execution_blocks )
291- elif self .benchmark_manager .execution_transactions :
292- execution_txs = []
293- for tx in self .benchmark_manager .execution_transactions :
294- execution_txs .extend (self .split_transaction (tx , gas_limit ))
295- all_blocks .append (Block (txs = execution_txs ))
296-
297- return BlockchainTest .from_test (
298- base_test = self ,
299- genesis_environment = self .env ,
300- pre = self .pre ,
301- post = self .post ,
302- blocks = all_blocks ,
303- )
304186 elif self .blocks is not None :
305187 return BlockchainTest .from_test (
306188 base_test = self ,
@@ -324,9 +206,7 @@ def generate_blockchain_test(self, fork: Fork) -> BlockchainTest:
324206 genesis_environment = self .env ,
325207 )
326208 else :
327- raise ValueError (
328- "Cannot create BlockchainTest without transactions, blocks, or benchmark_manager"
329- )
209+ raise ValueError ("Cannot create BlockchainTest without transactions or blocks" )
330210
331211 def generate (
332212 self ,
@@ -358,10 +238,5 @@ def execute(
358238 raise Exception (f"Unsupported execute format: { execute_format } " )
359239
360240
361- def create_benchmark_manager () -> BenchmarkManager :
362- """Create a new BenchmarkManager instance for phase-aware benchmark testing."""
363- return BenchmarkManager ()
364-
365-
366241BenchmarkTestSpec = Callable [[str ], Generator [BenchmarkTest , None , None ]]
367242BenchmarkTestFiller = Type [BenchmarkTest ]
0 commit comments