@@ -250,27 +250,71 @@ class GethFixtureConsumer(
250250):
251251 """Geth's implementation of the fixture consumer."""
252252
253- def consume_blockchain_test (
253+ # ------------------------------------ eof test -----------------------------------------------
254+
255+ def extract_int_from_subprocess_string (
256+ self , s : str , substring_of_interest_prefix : str
257+ ) -> int | None :
258+ """Hacky method to extract relevant substring from string returned by subprocess execution.""" # noqa: E501
259+ # get everything after this substring occurrence, then remove everything not in [0,9]
260+ relevant_substring = re .sub (r"\D" , "" , s .split ('total executed"=' , 1 )[1 ])
261+ if relevant_substring .isdigit ():
262+ return int (relevant_substring )
263+ else :
264+ return None
265+
266+ def eofparse_subprocess_output_to_dict (
267+ self , process_result : str , fixture_name : str | None , fork_name : str
268+ ) -> Dict :
269+ """Take subprocess output from geth's eofparse, a fixture_name and a fork name and return relevant data as dict.""" # noqa: E501
270+ # remove whitespaces if more than 1 whitespace occurs at a time
271+ process_result_cleaned : str = re .sub (r"\s+" , " " , process_result ).strip ()
272+
273+ # determine amount of total tests
274+ total_tests_amount : int | None = self .extract_int_from_subprocess_string (
275+ process_result_cleaned , 'total executed"='
276+ )
277+
278+ # determine amount of passed tests
279+ passed_tests_amount : int | None = self .extract_int_from_subprocess_string (
280+ process_result_cleaned , "tests passed="
281+ )
282+
283+ # determine if all tests of this test vector passed
284+ all_tests_passed : bool = False
285+ if total_tests_amount is not None and passed_tests_amount is not None :
286+ if total_tests_amount == passed_tests_amount :
287+ all_tests_passed = True
288+
289+ # return relevant data as dict
290+ return {
291+ "name" : fixture_name ,
292+ "pass" : all_tests_passed ,
293+ "stateRoot" : None ,
294+ "fork" : fork_name ,
295+ }
296+
297+ def consume_eof_test_file (
254298 self ,
255299 fixture_path : Path ,
256300 fixture_name : Optional [str ] = None ,
257301 debug_output_path : Optional [Path ] = None ,
258- ):
302+ ) -> List [ Dict [ str , Any ]] :
259303 """
260- Consume a single blockchain test.
304+ Consume an entire EOF validation test file .
261305
262- The `evm blocktest` command takes the `--run` argument which can be used to select a
263- specific fixture from the fixture file when executing.
306+
307+ The `evm eofparse` will always validate all the eof byte codes contained in a file without
308+ the possibility of selecting a single test, so this function is cached in order to only
309+ call the command once and `consume_eof_test` can simply select the result that was
310+ requested.
264311 """
265- subcommand = "blocktest "
312+ subcommand = "eofparse "
266313 global_options = []
267- subcommand_options = []
314+ subcommand_options = ["--test" ]
268315 if debug_output_path :
269316 global_options += ["--verbosity" , "100" ]
270- subcommand_options += ["--trace" ]
271-
272- if fixture_name :
273- subcommand_options += ["--run" , re .escape (fixture_name )]
317+ # --trace does not exist for eofparse
274318
275319 command = (
276320 [str (self .binary )]
@@ -290,19 +334,69 @@ def consume_blockchain_test(
290334 f"Unexpected exit code:\n { ' ' .join (command )} \n \n Error:\n { result .stderr } "
291335 )
292336
337+ result_json = [
338+ self .eofparse_subprocess_output_to_dict (result .stderr , fixture_name , "Osaka" )
339+ ]
340+ if not isinstance (result_json , list ):
341+ raise Exception (f"Unexpected result from evm eofparse: { result_json } " )
342+ return result_json
343+
293344 def consume_eof_test (
294345 self ,
295346 fixture_path : Path ,
296347 fixture_name : Optional [str ] = None ,
297348 debug_output_path : Optional [Path ] = None ,
298349 ):
299- """Consume an EOF validation test (valid yes/no) without running any EOF code."""
300- subcommand = "eofparse"
350+ """
351+ Consume a single eof test.
352+
353+ Uses the cached result from `consume_eof_test_file` in order to not call the command
354+ every time an select a single result from there.
355+ """
356+ file_results = self .consume_eof_test_file (
357+ fixture_path = fixture_path ,
358+ fixture_name = fixture_name ,
359+ debug_output_path = debug_output_path ,
360+ )
361+ if fixture_name :
362+ test_result = [
363+ test_result for test_result in file_results if test_result ["name" ] == fixture_name
364+ ]
365+ assert len (test_result ) < 2 , f"Multiple test results for { fixture_name } "
366+ assert len (test_result ) == 1 , f"Test result for { fixture_name } missing"
367+ assert test_result [0 ]["pass" ], f"EOF test failed: { test_result [0 ]['error' ]} "
368+ else :
369+ if any (not test_result ["pass" ] for test_result in file_results ):
370+ exception_text = "EOF test failed: \n " + "\n " .join (
371+ f"{ test_result ['name' ]} : " + test_result ["error" ]
372+ for test_result in file_results
373+ if not test_result ["pass" ]
374+ )
375+ raise Exception (exception_text )
376+
377+ # ---------------------------------- blockchain test ------------------------------------------
378+
379+ def consume_blockchain_test (
380+ self ,
381+ fixture_path : Path ,
382+ fixture_name : Optional [str ] = None ,
383+ debug_output_path : Optional [Path ] = None ,
384+ ):
385+ """
386+ Consume a single blockchain test.
387+
388+ The `evm blocktest` command takes the `--run` argument which can be used to select a
389+ specific fixture from the fixture file when executing.
390+ """
391+ subcommand = "blocktest"
301392 global_options = []
302- subcommand_options = ["--test" ]
393+ subcommand_options = []
303394 if debug_output_path :
304395 global_options += ["--verbosity" , "100" ]
305- # --trace does not exist for eofparse
396+ subcommand_options += ["--trace" ]
397+
398+ if fixture_name :
399+ subcommand_options += ["--run" , re .escape (fixture_name )]
306400
307401 command = (
308402 [str (self .binary )]
@@ -322,6 +416,8 @@ def consume_eof_test(
322416 f"Unexpected exit code:\n { ' ' .join (command )} \n \n Error:\n { result .stderr } "
323417 )
324418
419+ # ------------------------------------ state test ---------------------------------------------
420+
325421 @cache # noqa
326422 def consume_state_test_file (
327423 self ,
@@ -361,6 +457,7 @@ def consume_state_test_file(
361457 )
362458
363459 result_json = json .loads (result .stdout )
460+ print ("Output from json.loads(result.stdout):" , result_json )
364461 if not isinstance (result_json , list ):
365462 raise Exception (f"Unexpected result from evm statetest: { result_json } " )
366463 return result_json
0 commit comments