5
5
import logging as logger
6
6
import json
7
7
from time import time
8
+ import pytest
8
9
9
10
10
11
class TestJolteonConsensusRPC :
@@ -59,8 +60,13 @@ def test_replica_state_retrieval(self, api: BlockchainApi, config: ApiConfig):
59
60
logger .info (f" Storage blocks: { replica_state ['storage_block_count' ]} " )
60
61
61
62
except Exception as e :
62
- logger .error (f"Error testing replica state: { e } " )
63
- raise
63
+ error_msg = str (e )
64
+ if "Method not found" in error_msg :
65
+ logger .warning ("Jolteon replica state RPC method not available in this environment" )
66
+ pytest .skip ("Jolteon replica state RPC method not implemented" )
67
+ else :
68
+ logger .error (f"Error testing replica state: { e } " )
69
+ raise
64
70
65
71
@mark .test_key ('JOLTEON-RPC-002' )
66
72
def test_round_progression (self , api : BlockchainApi , config : ApiConfig ):
@@ -79,7 +85,7 @@ def test_round_progression(self, api: BlockchainApi, config: ApiConfig):
79
85
80
86
if len (consensus_states ) < 2 :
81
87
logger .warning ("Insufficient consensus data for round progression analysis" )
82
- return
88
+ pytest . skip ( "Jolteon consensus RPC methods not available or insufficient data" )
83
89
84
90
# Analyze round progression over time
85
91
logger .info (f"Analyzed { len (consensus_states )} consensus state samples over { monitoring_duration } s" )
@@ -129,11 +135,11 @@ def test_quorum_certificate_formation(self, api: BlockchainApi, config: ApiConfi
129
135
130
136
try :
131
137
# Get consensus states for blocks
132
- consensus_states = self ._get_consensus_states_for_blocks (api , max_blocks = 5 )
138
+ consensus_states = self ._get_consensus_states_over_time (api , monitoring_duration = 30 , sample_interval = 6 )
133
139
134
140
if len (consensus_states ) < 2 :
135
141
logger .warning ("Insufficient QC data for analysis" )
136
- return
142
+ pytest . skip ( "Jolteon consensus RPC methods not available or insufficient data" )
137
143
138
144
# Analyze QC progression across blocks
139
145
logger .info (f"Analyzed { len (consensus_states )} QC states" )
@@ -221,6 +227,11 @@ def test_timeout_certificate_handling(self, api: BlockchainApi, config: ApiConfi
221
227
error_msg = str (e )
222
228
if "No timeout certificate available" in error_msg :
223
229
logger .info ("ℹ️ No Timeout Certificate available (normal in happy path)" )
230
+ elif "Method not found" in error_msg :
231
+ logger .warning ("Jolteon timeout certificate RPC method not available in this environment" )
232
+ pytest .skip ("Jolteon timeout certificate RPC method not implemented" )
233
+ elif "Connection refused" in error_msg :
234
+ raise AssertionError (f"Connection failed when checking TC: { e } " )
224
235
else :
225
236
logger .error (f"Error checking TC: { e } " )
226
237
raise
@@ -236,52 +247,62 @@ def test_consensus_state_consistency(self, api: BlockchainApi, config: ApiConfig
236
247
"""
237
248
logger .info ("Starting Jolteon consensus state consistency test" )
238
249
239
- # Get data from all endpoints
240
- replica_state_result = api .substrate .rpc_request ("jolteon_getReplicaState" , [])
241
- round_info_result = api .substrate .rpc_request ("jolteon_getRoundInfo" , [])
242
- qc_result = api .substrate .rpc_request ("jolteon_getHighestQC" , [])
243
-
244
- assert all ([replica_state_result , round_info_result , qc_result ]), "Failed to get consensus state from all endpoints"
245
-
246
- replica_state = replica_state_result ['result' ]
247
- round_info = round_info_result ['result' ]
248
- qc = qc_result ['result' ]
249
-
250
- logger .info (f"Replica state: { replica_state } " )
251
- logger .info (f"Round info: { round_info } " )
252
- logger .info (f"QC: { qc } " )
253
-
254
- # Verify round consistency between endpoints
255
- assert replica_state ['r_curr' ] == round_info ['r_curr' ], \
256
- f"Current round mismatch: replica_state={ replica_state ['r_curr' ]} , round_info={ round_info ['r_curr' ]} "
257
-
258
- assert replica_state ['r_vote' ] == round_info ['r_vote' ], \
259
- f"Voted round mismatch: replica_state={ replica_state ['r_vote' ]} , round_info={ round_info ['r_vote' ]} "
260
-
261
- assert replica_state ['r_lock' ] == round_info ['r_lock' ], \
262
- f"Locked round mismatch: replica_state={ replica_state ['r_lock' ]} , round_info={ round_info ['r_lock' ]} "
263
-
264
- # Verify QC consistency
265
- assert replica_state ['qc_high' ]['round' ] == qc ['round' ], \
266
- f"QC round mismatch: replica_state={ replica_state ['qc_high' ]['round' ]} , qc={ qc ['round' ]} "
267
-
268
- assert replica_state ['qc_high' ]['block_hash' ] == qc ['block_hash' ], \
269
- f"QC block hash mismatch: replica_state={ replica_state ['qc_high' ]['block_hash' ]} , qc={ qc ['block_hash' ]} "
270
-
271
- assert replica_state ['qc_high' ]['vote_count' ] == qc ['vote_count' ], \
272
- f"QC vote count mismatch: replica_state={ replica_state ['qc_high' ]['vote_count' ]} , qc={ qc ['vote_count' ]} "
273
-
274
- # Verify logical consistency
275
- assert replica_state ['r_curr' ] >= replica_state ['r_vote' ], \
276
- f"Current round should be >= voted round: { replica_state ['r_curr' ]} < { replica_state ['r_vote' ]} "
277
-
278
- assert replica_state ['r_vote' ] >= replica_state ['r_lock' ], \
279
- f"Voted round should be >= locked round: { replica_state ['r_vote' ]} < { replica_state ['r_lock' ]} "
280
-
281
- assert replica_state ['qc_high' ]['round' ] <= replica_state ['r_curr' ], \
282
- f"QC round should be <= current round: { replica_state ['qc_high' ]['round' ]} > { replica_state ['r_curr' ]} "
283
-
284
- logger .info ("✅ Consensus state consistency test passed" )
250
+ try :
251
+ # Get data from all endpoints
252
+ replica_state_result = api .substrate .rpc_request ("jolteon_getReplicaState" , [])
253
+ round_info_result = api .substrate .rpc_request ("jolteon_getRoundInfo" , [])
254
+ qc_result = api .substrate .rpc_request ("jolteon_getHighestQC" , [])
255
+
256
+ assert all ([replica_state_result , round_info_result , qc_result ]), "Failed to get consensus state from all endpoints"
257
+
258
+ replica_state = replica_state_result ['result' ]
259
+ round_info = round_info_result ['result' ]
260
+ qc = qc_result ['result' ]
261
+
262
+ logger .info (f"Replica state: { replica_state } " )
263
+ logger .info (f"Round info: { round_info } " )
264
+ logger .info (f"QC: { qc } " )
265
+
266
+ # Verify round consistency between endpoints
267
+ assert replica_state ['r_curr' ] == round_info ['r_curr' ], \
268
+ f"Current round mismatch: replica_state={ replica_state ['r_curr' ]} , round_info={ round_info ['r_curr' ]} "
269
+
270
+ assert replica_state ['r_vote' ] == round_info ['r_vote' ], \
271
+ f"Voted round mismatch: replica_state={ replica_state ['r_vote' ]} , round_info={ round_info ['r_vote' ]} "
272
+
273
+ assert replica_state ['r_lock' ] == round_info ['r_lock' ], \
274
+ f"Locked round mismatch: replica_state={ replica_state ['r_lock' ]} , round_info={ round_info ['r_lock' ]} "
275
+
276
+ # Verify QC consistency
277
+ assert replica_state ['qc_high' ]['round' ] == qc ['round' ], \
278
+ f"QC round mismatch: replica_state={ replica_state ['qc_high' ]['round' ]} , qc={ qc ['round' ]} "
279
+
280
+ assert replica_state ['qc_high' ]['block_hash' ] == qc ['block_hash' ], \
281
+ f"QC block hash mismatch: replica_state={ replica_state ['qc_high' ]['block_hash' ]} , qc={ qc ['block_hash' ]} "
282
+
283
+ assert replica_state ['qc_high' ]['vote_count' ] == qc ['vote_count' ], \
284
+ f"QC vote count mismatch: replica_state={ replica_state ['qc_high' ]['vote_count' ]} , qc={ qc ['vote_count' ]} "
285
+
286
+ # Verify logical consistency
287
+ assert replica_state ['r_curr' ] >= replica_state ['r_vote' ], \
288
+ f"Current round should be >= voted round: { replica_state ['r_curr' ]} < { replica_state ['r_vote' ]} "
289
+
290
+ assert replica_state ['r_vote' ] >= replica_state ['r_lock' ], \
291
+ f"Voted round should be >= locked round: { replica_state ['r_vote' ]} < { replica_state ['r_lock' ]} "
292
+
293
+ assert replica_state ['qc_high' ]['round' ] <= replica_state ['r_curr' ], \
294
+ f"QC round should be <= current round: { replica_state ['qc_high' ]['round' ]} > { replica_state ['r_curr' ]} "
295
+
296
+ logger .info ("✅ Consensus state consistency test passed" )
297
+
298
+ except Exception as e :
299
+ error_msg = str (e )
300
+ if "Method not found" in error_msg :
301
+ logger .warning ("Jolteon consensus state RPC methods not available in this environment" )
302
+ pytest .skip ("Jolteon consensus state RPC methods not implemented" )
303
+ else :
304
+ logger .error (f"Error in consensus state consistency test: { e } " )
305
+ raise
285
306
286
307
@mark .test_key ('JOLTEON-RPC-006' )
287
308
def test_jolteon_safety_properties (self , api : BlockchainApi , config : ApiConfig ):
@@ -297,11 +318,11 @@ def test_jolteon_safety_properties(self, api: BlockchainApi, config: ApiConfig):
297
318
298
319
try :
299
320
# Get consensus states for blocks
300
- consensus_states = self ._get_consensus_states_for_blocks (api , max_blocks = 10 )
321
+ consensus_states = self ._get_consensus_states_over_time (api , monitoring_duration = 60 , sample_interval = 6 )
301
322
302
323
if len (consensus_states ) < 2 :
303
324
logger .warning ("Insufficient data for safety analysis" )
304
- return
325
+ pytest . skip ( "Jolteon consensus RPC methods not available or insufficient data" )
305
326
306
327
logger .info (f"Analyzed { len (consensus_states )} consensus states for safety properties" )
307
328
@@ -357,11 +378,11 @@ def test_jolteon_liveness_properties(self, api: BlockchainApi, config: ApiConfig
357
378
358
379
try :
359
380
# Get consensus states for blocks
360
- consensus_states = self ._get_consensus_states_for_blocks (api , max_blocks = 15 )
381
+ consensus_states = self ._get_consensus_states_over_time (api , monitoring_duration = 90 , sample_interval = 6 )
361
382
362
383
if len (consensus_states ) < 3 :
363
384
logger .warning ("Insufficient data for liveness analysis" )
364
- return
385
+ pytest . skip ( "Jolteon consensus RPC methods not available or insufficient data" )
365
386
366
387
logger .info (f"Analyzed { len (consensus_states )} consensus states for liveness properties" )
367
388
0 commit comments