@@ -15,6 +15,7 @@ use lightning::{check_added_monitors, check_closed_broadcast, check_closed_event
1515
1616use std:: panic:: RefUnwindSafe ;
1717use std:: path:: PathBuf ;
18+ use std:: sync:: RwLock ;
1819
1920pub ( crate ) fn do_read_write_remove_list_persist < K : KVStore + RefUnwindSafe > ( kv_store : & K ) {
2021 let data = [ 42u8 ; 32 ] ;
@@ -173,3 +174,148 @@ pub(crate) fn do_test_store<K: KVStore>(store_0: &K, store_1: &K) {
173174 // Make sure everything is persisted as expected after close.
174175 check_persisted_data ! ( CLOSED_CHANNEL_UPDATE_ID ) ;
175176}
177+
178+ // A `KVStore` impl for testing purposes that wraps all our `KVStore`s and asserts their synchronicity.
179+ pub ( crate ) struct TestSyncStore {
180+ serializer : RwLock < ( ) > ,
181+ test_store : TestStore ,
182+ fs_store : FilesystemStore ,
183+ sqlite_store : SqliteStore ,
184+ }
185+
186+ impl TestSyncStore {
187+ pub ( crate ) fn new ( dest_dir : PathBuf ) -> Self {
188+ let serializer = RwLock :: new ( ( ) ) ;
189+ let mut fs_dir = dest_dir. clone ( ) ;
190+ fs_dir. push ( "fs_store" ) ;
191+ let fs_store = FilesystemStore :: new ( fs_dir) ;
192+ let mut sql_dir = dest_dir. clone ( ) ;
193+ sql_dir. push ( "sqlite_store" ) ;
194+ let sqlite_store = SqliteStore :: new (
195+ sql_dir,
196+ Some ( "test_sync_db" . to_string ( ) ) ,
197+ Some ( "test_sync_table" . to_string ( ) ) ,
198+ )
199+ . unwrap ( ) ;
200+ let test_store = TestStore :: new ( ) ;
201+ Self { serializer, fs_store, sqlite_store, test_store }
202+ }
203+
204+ fn do_list (
205+ & self , primary_namespace : & str , secondary_namespace : & str ,
206+ ) -> std:: io:: Result < Vec < String > > {
207+ let fs_res = self . fs_store . list ( primary_namespace, secondary_namespace) ;
208+ let sqlite_res = self . sqlite_store . list ( primary_namespace, secondary_namespace) ;
209+ let test_res = self . test_store . list ( primary_namespace, secondary_namespace) ;
210+
211+ match fs_res {
212+ Ok ( mut list) => {
213+ list. sort ( ) ;
214+
215+ let mut sqlite_list = sqlite_res. unwrap ( ) ;
216+ sqlite_list. sort ( ) ;
217+ assert_eq ! ( list, sqlite_list) ;
218+
219+ let mut test_list = test_res. unwrap ( ) ;
220+ test_list. sort ( ) ;
221+ assert_eq ! ( list, test_list) ;
222+
223+ Ok ( list)
224+ }
225+ Err ( e) => {
226+ assert ! ( sqlite_res. is_err( ) ) ;
227+ assert ! ( test_res. is_err( ) ) ;
228+ Err ( e)
229+ }
230+ }
231+ }
232+ }
233+
234+ impl KVStore for TestSyncStore {
235+ fn read (
236+ & self , primary_namespace : & str , secondary_namespace : & str , key : & str ,
237+ ) -> std:: io:: Result < Vec < u8 > > {
238+ let _guard = self . serializer . read ( ) . unwrap ( ) ;
239+
240+ let fs_res = self . fs_store . read ( primary_namespace, secondary_namespace, key) ;
241+ let sqlite_res = self . sqlite_store . read ( primary_namespace, secondary_namespace, key) ;
242+ let test_res = self . test_store . read ( primary_namespace, secondary_namespace, key) ;
243+
244+ match fs_res {
245+ Ok ( read) => {
246+ assert_eq ! ( read, sqlite_res. unwrap( ) ) ;
247+ assert_eq ! ( read, test_res. unwrap( ) ) ;
248+ Ok ( read)
249+ }
250+ Err ( e) => {
251+ assert ! ( sqlite_res. is_err( ) ) ;
252+ assert_eq ! ( e. kind( ) , unsafe { sqlite_res. unwrap_err_unchecked( ) . kind( ) } ) ;
253+ assert ! ( test_res. is_err( ) ) ;
254+ assert_eq ! ( e. kind( ) , unsafe { test_res. unwrap_err_unchecked( ) . kind( ) } ) ;
255+ Err ( e)
256+ }
257+ }
258+ }
259+
260+ fn write (
261+ & self , primary_namespace : & str , secondary_namespace : & str , key : & str , buf : & [ u8 ] ,
262+ ) -> std:: io:: Result < ( ) > {
263+ let _guard = self . serializer . write ( ) . unwrap ( ) ;
264+ let fs_res = self . fs_store . write ( primary_namespace, secondary_namespace, key, buf) ;
265+ let sqlite_res = self . sqlite_store . write ( primary_namespace, secondary_namespace, key, buf) ;
266+ let test_res = self . test_store . write ( primary_namespace, secondary_namespace, key, buf) ;
267+
268+ assert ! ( self
269+ . do_list( primary_namespace, secondary_namespace)
270+ . unwrap( )
271+ . contains( & key. to_string( ) ) ) ;
272+
273+ match fs_res {
274+ Ok ( ( ) ) => {
275+ assert ! ( sqlite_res. is_ok( ) ) ;
276+ assert ! ( test_res. is_ok( ) ) ;
277+ Ok ( ( ) )
278+ }
279+ Err ( e) => {
280+ assert ! ( sqlite_res. is_err( ) ) ;
281+ assert ! ( test_res. is_err( ) ) ;
282+ Err ( e)
283+ }
284+ }
285+ }
286+
287+ fn remove (
288+ & self , primary_namespace : & str , secondary_namespace : & str , key : & str , lazy : bool ,
289+ ) -> std:: io:: Result < ( ) > {
290+ let _guard = self . serializer . write ( ) . unwrap ( ) ;
291+ let fs_res = self . fs_store . remove ( primary_namespace, secondary_namespace, key, lazy) ;
292+ let sqlite_res =
293+ self . sqlite_store . remove ( primary_namespace, secondary_namespace, key, lazy) ;
294+ let test_res = self . test_store . remove ( primary_namespace, secondary_namespace, key, lazy) ;
295+
296+ assert ! ( !self
297+ . do_list( primary_namespace, secondary_namespace)
298+ . unwrap( )
299+ . contains( & key. to_string( ) ) ) ;
300+
301+ match fs_res {
302+ Ok ( ( ) ) => {
303+ assert ! ( sqlite_res. is_ok( ) ) ;
304+ assert ! ( test_res. is_ok( ) ) ;
305+ Ok ( ( ) )
306+ }
307+ Err ( e) => {
308+ assert ! ( sqlite_res. is_err( ) ) ;
309+ assert ! ( test_res. is_err( ) ) ;
310+ Err ( e)
311+ }
312+ }
313+ }
314+
315+ fn list (
316+ & self , primary_namespace : & str , secondary_namespace : & str ,
317+ ) -> std:: io:: Result < Vec < String > > {
318+ let _guard = self . serializer . read ( ) . unwrap ( ) ;
319+ self . do_list ( primary_namespace, secondary_namespace)
320+ }
321+ }
0 commit comments