1
1
"""Pytest plugin that defines options and fixtures for client exceptions."""
2
2
3
- from typing import List
3
+ import pprint
4
+ from typing import Dict , List , Tuple
4
5
5
6
import pytest
6
7
from hive .client import ClientType
7
8
9
+ from ethereum_clis .clis .besu import BesuExceptionMapper
10
+ from ethereum_clis .clis .erigon import ErigonExceptionMapper
11
+ from ethereum_clis .clis .ethereumjs import EthereumJSExceptionMapper
12
+ from ethereum_clis .clis .ethrex import EthrexExceptionMapper
13
+ from ethereum_clis .clis .geth import GethExceptionMapper
14
+ from ethereum_clis .clis .nethermind import NethermindExceptionMapper
15
+ from ethereum_clis .clis .nimbus import NimbusExceptionMapper
16
+ from ethereum_clis .clis .reth import RethExceptionMapper
8
17
from ethereum_test_exceptions import ExceptionMapper
9
- from ethereum_test_fixtures import (
10
- BlockchainFixtureCommon ,
11
- )
12
-
13
- from .helpers .exceptions import EXCEPTION_MAPPERS
18
+ from ethereum_test_fixtures import BlockchainFixtureCommon
19
+ from ethereum_test_fixtures .blockchain import FixtureHeader
20
+
21
+
22
+ class GenesisBlockMismatchExceptionError (Exception ):
23
+ """Definers a mismatch exception between the client and fixture genesis blockhash."""
24
+
25
+ def __init__ (self , * , expected_header : FixtureHeader , got_genesis_block : Dict [str , str ]):
26
+ """Initialize the exception with the expected and received genesis block headers."""
27
+ message = (
28
+ "Genesis block hash mismatch.\n \n "
29
+ f"Expected: { expected_header .block_hash } \n "
30
+ f" Got: { got_genesis_block ['hash' ]} ."
31
+ )
32
+ differences , unexpected_fields = self .compare_models (
33
+ expected_header , FixtureHeader (** got_genesis_block )
34
+ )
35
+ if differences :
36
+ message += (
37
+ "\n \n Genesis block header field differences:\n "
38
+ f"{ pprint .pformat (differences , indent = 4 )} "
39
+ )
40
+ elif unexpected_fields :
41
+ message += (
42
+ "\n \n Un-expected genesis block header fields from client:\n "
43
+ f"{ pprint .pformat (unexpected_fields , indent = 4 )} "
44
+ "\n Is the fork configuration correct?"
45
+ )
46
+ else :
47
+ message += (
48
+ "There were no differences in the expected and received genesis block headers."
49
+ )
50
+ super ().__init__ (message )
51
+
52
+ @staticmethod
53
+ def compare_models (expected : FixtureHeader , got : FixtureHeader ) -> Tuple [Dict , List ]:
54
+ """Compare two FixtureHeader model instances and return their differences."""
55
+ differences = {}
56
+ unexpected_fields = []
57
+ for (exp_name , exp_value ), (got_name , got_value ) in zip (expected , got , strict = False ):
58
+ if "rlp" in exp_name or "fork" in exp_name : # ignore rlp as not verbose enough
59
+ continue
60
+ if exp_value != got_value :
61
+ differences [exp_name ] = {
62
+ "expected " : str (exp_value ),
63
+ "got (via rpc)" : str (got_value ),
64
+ }
65
+ if got_value is None :
66
+ unexpected_fields .append (got_name )
67
+ return differences , unexpected_fields
68
+
69
+
70
+ EXCEPTION_MAPPERS : Dict [str , ExceptionMapper ] = {
71
+ "go-ethereum" : GethExceptionMapper (),
72
+ "nethermind" : NethermindExceptionMapper (),
73
+ "erigon" : ErigonExceptionMapper (),
74
+ "besu" : BesuExceptionMapper (),
75
+ "reth" : RethExceptionMapper (),
76
+ "nimbus" : NimbusExceptionMapper (),
77
+ "ethereumjs" : EthereumJSExceptionMapper (),
78
+ "ethrex" : EthrexExceptionMapper (),
79
+ }
14
80
15
81
16
82
def pytest_addoption (parser ):
@@ -88,4 +154,4 @@ def strict_exception_matching(
88
154
fork_strict_exception_matching : bool ,
89
155
) -> bool :
90
156
"""Return True if the test should use strict exception matching."""
91
- return client_strict_exception_matching and fork_strict_exception_matching
157
+ return client_strict_exception_matching and fork_strict_exception_matching
0 commit comments