@@ -8,10 +8,11 @@ use mithril_common::store::{adapter::StoreAdapter, StoreError};
8
8
9
9
type Adapter = Box < dyn StoreAdapter < Key = Epoch , Record = HashMap < PartyId , SignerWithStake > > > ;
10
10
11
- /// Mocking trait for `VerificationKeyStore` .
11
+ /// Store and get signers verification keys for given epoch .
12
12
#[ async_trait]
13
13
pub trait VerificationKeyStorer : Sync + Send {
14
- /// Save the verification key, for the given [Signer] for the given [Epoch].
14
+ /// Save the verification key, for the given [Signer] for the given [Epoch], returns the
15
+ /// previous values if one already existed.
15
16
async fn save_verification_key (
16
17
& self ,
17
18
epoch : Epoch ,
@@ -88,24 +89,74 @@ impl VerificationKeyStorer for VerificationKeyStore {
88
89
}
89
90
}
90
91
92
+ /// Macro that generate tests that a [VerificationKeyStorer] must pass
91
93
#[ cfg( test) ]
92
- mod tests {
93
- use super :: * ;
94
+ macro_rules! test_verification_key_storer {
95
+ ( $suit_name: ident => $store_builder: expr) => {
96
+ #[ cfg( test) ]
97
+ mod $suit_name {
98
+ use crate :: store:: verification_key_store_test_suite as test_suite;
99
+
100
+ #[ tokio:: test]
101
+ async fn save_key_in_empty_store( ) {
102
+ test_suite:: save_key_in_empty_store( & $store_builder) . await ;
103
+ }
94
104
95
- use mithril_common:: store:: adapter:: MemoryAdapter ;
105
+ #[ tokio:: test]
106
+ async fn update_signer_in_store( ) {
107
+ test_suite:: update_signer_in_store( & $store_builder) . await ;
108
+ }
96
109
97
- fn init_store (
110
+ #[ tokio:: test]
111
+ async fn get_verification_keys_for_empty_epoch( ) {
112
+ test_suite:: get_verification_keys_for_empty_epoch( & $store_builder) . await ;
113
+ }
114
+
115
+ #[ tokio:: test]
116
+ async fn get_verification_keys_for_existing_epoch( ) {
117
+ test_suite:: get_verification_keys_for_existing_epoch( & $store_builder) . await ;
118
+ }
119
+
120
+ #[ tokio:: test]
121
+ async fn check_retention_limit( ) {
122
+ test_suite:: check_retention_limit( & $store_builder) . await ;
123
+ }
124
+ }
125
+ } ;
126
+ }
127
+
128
+ #[ cfg( test) ]
129
+ pub ( crate ) use test_verification_key_storer;
130
+
131
+ #[ macro_use]
132
+ #[ cfg( test) ]
133
+ pub mod test_suite {
134
+ use mithril_common:: entities:: { Epoch , PartyId , Signer , SignerWithStake } ;
135
+ use std:: collections:: { BTreeMap , HashMap } ;
136
+ use std:: sync:: Arc ;
137
+
138
+ use crate :: VerificationKeyStorer ;
139
+
140
+ /// A builder of [VerificationKeyStorer], the arguments are:
141
+ /// * initial_data
142
+ /// * optional retention limit
143
+ type StoreBuilder = dyn Fn (
144
+ Vec < ( Epoch , HashMap < PartyId , SignerWithStake > ) > ,
145
+ Option < usize > ,
146
+ ) -> Arc < dyn VerificationKeyStorer > ;
147
+
148
+ fn build_signers (
98
149
nb_epoch : u64 ,
99
- signers_per_epoch : u64 ,
100
- retention_limit : Option < usize > ,
101
- ) -> VerificationKeyStore {
102
- let mut values: Vec < ( Epoch , HashMap < PartyId , SignerWithStake > ) > = Vec :: new ( ) ;
150
+ signers_per_epoch : usize ,
151
+ ) -> Vec < ( Epoch , HashMap < PartyId , SignerWithStake > ) > {
152
+ let mut values = vec ! [ ] ;
103
153
104
154
for epoch in 1 ..=nb_epoch {
105
- let mut signers: HashMap < PartyId , SignerWithStake > = HashMap :: new ( ) ;
155
+ let mut signers: HashMap < PartyId , SignerWithStake > =
156
+ HashMap :: with_capacity ( signers_per_epoch) ;
106
157
107
158
for party_idx in 1 ..=signers_per_epoch {
108
- let party_id = format ! ( "{party_idx}" ) ;
159
+ let party_id = format ! ( "party_id:e{epoch}: {party_idx}" ) ;
109
160
signers. insert (
110
161
party_id. clone ( ) ,
111
162
SignerWithStake {
@@ -121,19 +172,12 @@ mod tests {
121
172
values. push ( ( Epoch ( epoch) , signers) ) ;
122
173
}
123
174
124
- let values = if !values. is_empty ( ) {
125
- Some ( values)
126
- } else {
127
- None
128
- } ;
129
- let adapter: MemoryAdapter < Epoch , HashMap < PartyId , SignerWithStake > > =
130
- MemoryAdapter :: new ( values) . unwrap ( ) ;
131
- VerificationKeyStore :: new ( Box :: new ( adapter) , retention_limit)
175
+ values
132
176
}
133
177
134
- # [ tokio :: test ]
135
- async fn save_key_in_empty_store ( ) {
136
- let store = init_store ( 0 , 0 , None ) ;
178
+ pub async fn save_key_in_empty_store ( store_builder : & StoreBuilder ) {
179
+ let signers = build_signers ( 0 , 0 ) ;
180
+ let store = store_builder ( signers , None ) ;
137
181
let res = store
138
182
. save_verification_key (
139
183
Epoch ( 0 ) ,
@@ -152,15 +196,15 @@ mod tests {
152
196
assert ! ( res. is_none( ) ) ;
153
197
}
154
198
155
- # [ tokio :: test ]
156
- async fn update_signer_in_store ( ) {
157
- let store = init_store ( 1 , 1 , None ) ;
199
+ pub async fn update_signer_in_store ( store_builder : & StoreBuilder ) {
200
+ let signers = build_signers ( 1 , 1 ) ;
201
+ let store = store_builder ( signers , None ) ;
158
202
let res = store
159
203
. save_verification_key (
160
204
Epoch ( 1 ) ,
161
205
SignerWithStake {
162
- party_id : "1" . to_string ( ) ,
163
- verification_key : "test " . to_string ( ) ,
206
+ party_id : "party_id:e1: 1" . to_string ( ) ,
207
+ verification_key : "new_vkey " . to_string ( ) ,
164
208
verification_key_signature : None ,
165
209
operational_certificate : None ,
166
210
kes_period : None ,
@@ -170,40 +214,50 @@ mod tests {
170
214
. await
171
215
. unwrap ( ) ;
172
216
173
- assert ! ( res. is_some( ) ) ;
174
217
assert_eq ! (
175
- SignerWithStake {
176
- party_id: "1" . to_string( ) ,
177
- verification_key: "vkey 1" . to_string( ) ,
218
+ Some ( SignerWithStake {
219
+ party_id: "party_id:e1: 1" . to_string( ) ,
220
+ verification_key: "vkey party_id:e1: 1" . to_string( ) ,
178
221
verification_key_signature: None ,
179
222
operational_certificate: None ,
180
223
kes_period: None ,
181
224
stake: 10 ,
182
- } ,
183
- res. unwrap ( ) ,
225
+ } ) ,
226
+ res,
184
227
) ;
185
228
}
186
229
187
- # [ tokio :: test ]
188
- async fn get_verification_keys_for_empty_epoch ( ) {
189
- let store = init_store ( 2 , 1 , None ) ;
230
+ pub async fn get_verification_keys_for_empty_epoch ( store_builder : & StoreBuilder ) {
231
+ let signers = build_signers ( 2 , 1 ) ;
232
+ let store = store_builder ( signers , None ) ;
190
233
let res = store. get_verification_keys ( Epoch ( 0 ) ) . await . unwrap ( ) ;
191
234
192
235
assert ! ( res. is_none( ) ) ;
193
236
}
194
237
195
- #[ tokio:: test]
196
- async fn get_verification_keys_for_existing_epoch ( ) {
197
- let store = init_store ( 2 , 2 , None ) ;
198
- let res = store. get_verification_keys ( Epoch ( 1 ) ) . await . unwrap ( ) ;
238
+ pub async fn get_verification_keys_for_existing_epoch ( store_builder : & StoreBuilder ) {
239
+ let signers = build_signers ( 2 , 2 ) ;
240
+ let expected_signers: Option < BTreeMap < PartyId , Signer > > = signers
241
+ . iter ( )
242
+ . filter ( |( e, _) | e == 1 )
243
+ . cloned ( )
244
+ . map ( |( _, signers) | {
245
+ BTreeMap :: from_iter ( signers. into_iter ( ) . map ( |( p, s) | ( p, s. into ( ) ) ) )
246
+ } )
247
+ . next ( ) ;
248
+ let store = store_builder ( signers, None ) ;
249
+ let res = store
250
+ . get_verification_keys ( Epoch ( 1 ) )
251
+ . await
252
+ . unwrap ( )
253
+ . map ( |x| BTreeMap :: from_iter ( x. into_iter ( ) ) ) ;
199
254
200
- assert ! ( res. is_some( ) ) ;
201
- assert_eq ! ( 2 , res. unwrap( ) . len( ) ) ;
255
+ assert_eq ! ( expected_signers, res) ;
202
256
}
203
257
204
- # [ tokio :: test ]
205
- async fn check_retention_limit ( ) {
206
- let store = init_store ( 2 , 2 , Some ( 2 ) ) ;
258
+ pub async fn check_retention_limit ( store_builder : & StoreBuilder ) {
259
+ let signers = build_signers ( 2 , 2 ) ;
260
+ let store = store_builder ( signers , Some ( 2 ) ) ;
207
261
assert ! ( store
208
262
. get_verification_keys( Epoch ( 1 ) )
209
263
. await
@@ -223,10 +277,42 @@ mod tests {
223
277
)
224
278
. await
225
279
. unwrap ( ) ;
226
- assert ! ( store
227
- . get_verification_keys( Epoch ( 1 ) )
228
- . await
229
- . unwrap( )
230
- . is_none( ) ) ;
280
+ let first_epoch_keys = store. get_verification_keys ( Epoch ( 1 ) ) . await . unwrap ( ) ;
281
+ assert_eq ! ( None , first_epoch_keys) ;
282
+ }
283
+ }
284
+
285
+ #[ cfg( test) ]
286
+ mod tests {
287
+ use mithril_common:: {
288
+ entities:: { Epoch , PartyId , SignerWithStake } ,
289
+ store:: adapter:: MemoryAdapter ,
290
+ } ;
291
+ use std:: { collections:: HashMap , sync:: Arc } ;
292
+
293
+ use crate :: { VerificationKeyStore , VerificationKeyStorer } ;
294
+
295
+ pub fn init_store (
296
+ initial_data : Vec < ( Epoch , HashMap < PartyId , SignerWithStake > ) > ,
297
+ retention_limit : Option < usize > ,
298
+ ) -> Arc < dyn VerificationKeyStorer > {
299
+ let values = if initial_data. is_empty ( ) {
300
+ None
301
+ } else {
302
+ Some ( initial_data)
303
+ } ;
304
+
305
+ let adapter: MemoryAdapter < Epoch , HashMap < PartyId , SignerWithStake > > =
306
+ MemoryAdapter :: new ( values) . unwrap ( ) ;
307
+
308
+ Arc :: new ( VerificationKeyStore :: new (
309
+ Box :: new ( adapter) ,
310
+ retention_limit,
311
+ ) )
231
312
}
313
+
314
+ test_verification_key_storer ! (
315
+ test_verification_key_store =>
316
+ crate :: store:: verification_key_store:: tests:: init_store
317
+ ) ;
232
318
}
0 commit comments