@@ -771,7 +771,21 @@ impl<P: Params> EntityManager<P> {
771
771
772
772
#[ cfg( test) ]
773
773
mod tests {
774
-
774
+ //! Tests for the entity manager.
775
+ //!
776
+ //! We implement a simple database for u128 counters, identified by u64 ids,
777
+ //! with both an in-memory and a file-based implementation.
778
+ //!
779
+ //! The database does internal consistency checks, to ensure that each
780
+ //! entity is only ever accessed by a single tokio task at a time, and to
781
+ //! ensure that wakeup and shutdown events are interleaved.
782
+ //!
783
+ //! We also check that the database behaves correctly by comparing with an
784
+ //! in-memory implementation.
785
+ //!
786
+ //! Database operations are done in parallel, so the fact that we are using
787
+ //! AtomicRefCell provides another test - if there was parallel write access
788
+ //! to a single entity due to a bug, it would panic.
775
789
use std:: collections:: HashMap ;
776
790
777
791
use n0_future:: { BufferedStreamExt , StreamExt } ;
@@ -793,6 +807,10 @@ mod tests {
793
807
}
794
808
795
809
mod mem {
810
+ //! The in-memory database uses a HashMap in the global state to store
811
+ //! the values of the counters. Loading means reading from the global
812
+ //! state into the entity state, and persisting means writing to the
813
+ //! global state from the entity state.
796
814
use std:: {
797
815
collections:: { HashMap , HashSet } ,
798
816
sync:: { Arc , Mutex } ,
@@ -957,6 +975,7 @@ mod tests {
957
975
}
958
976
959
977
mod fs {
978
+ //! The fs db uses one file per counter, stored as a 16-byte big-endian u128.
960
979
use std:: {
961
980
collections:: HashSet ,
962
981
path:: { Path , PathBuf } ,
@@ -1121,6 +1140,15 @@ mod tests {
1121
1140
1122
1141
async fn check_consistency ( & self , values : HashMap < u64 , u128 > ) {
1123
1142
let global = self . global . lock ( ) . unwrap ( ) ;
1143
+ for ( id, value) in & values {
1144
+ let path = get_path ( & global. path , * id) ;
1145
+ let disk_value = match std:: fs:: read ( path) {
1146
+ Ok ( data) => u128:: from_be_bytes ( data. try_into ( ) . unwrap ( ) ) ,
1147
+ Err ( e) if e. kind ( ) == std:: io:: ErrorKind :: NotFound => 0 ,
1148
+ Err ( _) => panic ! ( "Failed to read disk state for id {id}" ) ,
1149
+ } ;
1150
+ assert_eq ! ( disk_value, * value, "Disk value mismatch for id {id}" ) ;
1151
+ }
1124
1152
for id in values. keys ( ) {
1125
1153
let log = global. log . get ( & id) . unwrap ( ) ;
1126
1154
assert ! (
0 commit comments