@@ -83,3 +83,173 @@ where
8383 . map ( |s| hex:: decode ( s. strip_prefix ( "0x" ) . unwrap_or ( & s) ) . map_err ( serde:: de:: Error :: custom) )
8484 . collect ( )
8585}
86+
87+ #[ cfg( test) ]
88+ mod tests {
89+ use commonware_codec:: Write as _;
90+ use commonware_cryptography:: Signer as _;
91+
92+ use super :: * ;
93+
94+ fn create_valid_public_key_bytes ( ) -> Vec < u8 > {
95+ let private_key =
96+ ed25519:: PrivateKey :: from ( ed25519_consensus:: SigningKey :: from ( [ 42u8 ; 32 ] ) ) ;
97+ let public_key = private_key. public_key ( ) ;
98+ let mut bytes = Vec :: new ( ) ;
99+ public_key. write ( & mut bytes) ;
100+ bytes
101+ }
102+
103+ #[ test]
104+ fn default_consensus_config ( ) {
105+ let config = ConsensusConfig :: default ( ) ;
106+ assert ! ( config. validator_key. is_none( ) ) ;
107+ assert_eq ! ( config. threshold, DEFAULT_THRESHOLD ) ;
108+ assert ! ( config. participants. is_empty( ) ) ;
109+ }
110+
111+ #[ test]
112+ fn default_threshold_constant ( ) {
113+ assert_eq ! ( DEFAULT_THRESHOLD , 2 ) ;
114+ assert_eq ! ( default_threshold( ) , DEFAULT_THRESHOLD ) ;
115+ }
116+
117+ #[ test]
118+ fn serde_json_roundtrip ( ) {
119+ let pk_bytes = create_valid_public_key_bytes ( ) ;
120+ let config = ConsensusConfig {
121+ validator_key : Some ( PathBuf :: from ( "/path/to/key" ) ) ,
122+ threshold : 3 ,
123+ participants : vec ! [ pk_bytes] ,
124+ } ;
125+ let serialized = serde_json:: to_string ( & config) . expect ( "serialize" ) ;
126+ let deserialized: ConsensusConfig = serde_json:: from_str ( & serialized) . expect ( "deserialize" ) ;
127+ assert_eq ! ( config, deserialized) ;
128+ }
129+
130+ #[ test]
131+ fn serde_toml_roundtrip ( ) {
132+ let config =
133+ ConsensusConfig { validator_key : Some ( "/path/to/key" . into ( ) ) , ..Default :: default ( ) } ;
134+ let serialized = toml:: to_string ( & config) . expect ( "serialize toml" ) ;
135+ let deserialized: ConsensusConfig = toml:: from_str ( & serialized) . expect ( "deserialize toml" ) ;
136+ assert_eq ! ( config, deserialized) ;
137+ }
138+
139+ #[ test]
140+ fn serde_defaults_applied ( ) {
141+ let config: ConsensusConfig = serde_json:: from_str ( "{}" ) . expect ( "deserialize" ) ;
142+ assert ! ( config. validator_key. is_none( ) ) ;
143+ assert_eq ! ( config. threshold, DEFAULT_THRESHOLD ) ;
144+ assert ! ( config. participants. is_empty( ) ) ;
145+ }
146+
147+ #[ test]
148+ fn serde_partial_threshold ( ) {
149+ let config: ConsensusConfig =
150+ serde_json:: from_str ( r#"{"threshold": 7}"# ) . expect ( "deserialize" ) ;
151+ assert_eq ! ( config. threshold, 7 ) ;
152+ assert ! ( config. validator_key. is_none( ) ) ;
153+ assert ! ( config. participants. is_empty( ) ) ;
154+ }
155+
156+ #[ test]
157+ fn serde_partial_validator_key ( ) {
158+ let config: ConsensusConfig =
159+ serde_json:: from_str ( r#"{"validator_key": "/etc/key"}"# ) . expect ( "deserialize" ) ;
160+ assert_eq ! ( config. validator_key, Some ( PathBuf :: from( "/etc/key" ) ) ) ;
161+ assert_eq ! ( config. threshold, DEFAULT_THRESHOLD ) ;
162+ }
163+
164+ #[ test]
165+ fn deserialize_participants_with_0x_prefix ( ) {
166+ let pk_bytes = create_valid_public_key_bytes ( ) ;
167+ let hex_with_prefix = format ! ( "0x{}" , hex:: encode( & pk_bytes) ) ;
168+ let json = format ! ( r#"{{"participants": ["{}"]}}"# , hex_with_prefix) ;
169+
170+ let config: ConsensusConfig = serde_json:: from_str ( & json) . expect ( "deserialize" ) ;
171+ assert_eq ! ( config. participants. len( ) , 1 ) ;
172+ assert_eq ! ( config. participants[ 0 ] , pk_bytes) ;
173+ }
174+
175+ #[ test]
176+ fn deserialize_participants_without_prefix ( ) {
177+ let pk_bytes = create_valid_public_key_bytes ( ) ;
178+ let hex_without_prefix = hex:: encode ( & pk_bytes) ;
179+ let json = format ! ( r#"{{"participants": ["{}"]}}"# , hex_without_prefix) ;
180+
181+ let config: ConsensusConfig = serde_json:: from_str ( & json) . expect ( "deserialize" ) ;
182+ assert_eq ! ( config. participants. len( ) , 1 ) ;
183+ assert_eq ! ( config. participants[ 0 ] , pk_bytes) ;
184+ }
185+
186+ #[ test]
187+ fn build_validator_set_empty ( ) {
188+ let config = ConsensusConfig :: default ( ) ;
189+ let result = config. build_validator_set ( ) . expect ( "build empty set" ) ;
190+ assert ! ( result. is_empty( ) ) ;
191+ }
192+
193+ #[ test]
194+ fn build_validator_set_single_key ( ) {
195+ let pk_bytes = create_valid_public_key_bytes ( ) ;
196+ let config = ConsensusConfig { participants : vec ! [ pk_bytes] , ..Default :: default ( ) } ;
197+ let result = config. build_validator_set ( ) . expect ( "build validator set" ) ;
198+ assert_eq ! ( result. len( ) , 1 ) ;
199+ }
200+
201+ #[ test]
202+ fn build_validator_set_multiple_keys ( ) {
203+ let keys: Vec < _ > = ( 1 ..=3u8 )
204+ . map ( |i| {
205+ let pk = ed25519:: PrivateKey :: from ( ed25519_consensus:: SigningKey :: from ( [ i; 32 ] ) ) ;
206+ let mut bytes = Vec :: new ( ) ;
207+ pk. public_key ( ) . write ( & mut bytes) ;
208+ bytes
209+ } )
210+ . collect ( ) ;
211+
212+ let config = ConsensusConfig { participants : keys, threshold : 2 , ..Default :: default ( ) } ;
213+
214+ let result = config. build_validator_set ( ) . expect ( "build validator set" ) ;
215+ assert_eq ! ( result. len( ) , 3 ) ;
216+ }
217+
218+ #[ test]
219+ fn build_validator_set_invalid_length ( ) {
220+ let config = ConsensusConfig { participants : vec ! [ vec![ 0u8 ; 16 ] ] , ..Default :: default ( ) } ;
221+ let result = config. build_validator_set ( ) ;
222+ assert ! ( result. is_err( ) ) ;
223+ assert ! ( matches!( result. unwrap_err( ) , ConfigError :: InvalidParticipantKeyLength ( 16 ) ) ) ;
224+ }
225+
226+ #[ test]
227+ fn participants_hex_serialization ( ) {
228+ let pk_bytes = create_valid_public_key_bytes ( ) ;
229+ let expected_hex = hex:: encode ( & pk_bytes) ;
230+ let config = ConsensusConfig { participants : vec ! [ pk_bytes] , ..Default :: default ( ) } ;
231+
232+ let serialized = serde_json:: to_string ( & config) . expect ( "serialize" ) ;
233+ assert ! ( serialized. contains( & expected_hex) ) ;
234+ }
235+
236+ #[ test]
237+ fn consensus_config_clone_and_eq ( ) {
238+ let pk_bytes = create_valid_public_key_bytes ( ) ;
239+ let config = ConsensusConfig {
240+ validator_key : Some ( PathBuf :: from ( "/custom/path" ) ) ,
241+ threshold : 10 ,
242+ participants : vec ! [ pk_bytes] ,
243+ } ;
244+ assert_eq ! ( config, config. clone( ) ) ;
245+ assert_ne ! ( config, ConsensusConfig :: default ( ) ) ;
246+ }
247+
248+ #[ test]
249+ fn consensus_config_debug ( ) {
250+ let config = ConsensusConfig :: default ( ) ;
251+ let debug = format ! ( "{:?}" , config) ;
252+ assert ! ( debug. contains( "ConsensusConfig" ) ) ;
253+ assert ! ( debug. contains( "threshold" ) ) ;
254+ }
255+ }
0 commit comments