@@ -2109,4 +2109,78 @@ mod tests {
21092109 . count( )
21102110 == 2 ) )
21112111 }
2112+
2113+ #[ test]
2114+ fn mounted_reducer_ids_are_depth_first ( ) {
2115+ use spacetimedb_lib:: db:: raw_def:: v10:: {
2116+ RawModuleDefV10Builder , RawModuleDefV10Section , RawModuleMountV10 ,
2117+ } ;
2118+
2119+ // baz library: 1 reducer
2120+ let mut baz_builder = RawModuleDefV10Builder :: new ( ) ;
2121+ baz_builder. add_reducer ( "baz_reduce" , ProductType :: unit ( ) ) ;
2122+
2123+ // auth library: 1 own reducer, mounts baz
2124+ let mut auth_builder = RawModuleDefV10Builder :: new ( ) ;
2125+ auth_builder. add_reducer ( "auth_verify" , ProductType :: unit ( ) ) ;
2126+ let mut auth_raw = auth_builder. finish ( ) ;
2127+ auth_raw. sections . push ( RawModuleDefV10Section :: Mounts ( vec ! [ RawModuleMountV10 {
2128+ namespace: "baz" . to_string( ) ,
2129+ module: baz_builder. finish( ) ,
2130+ } ] ) ) ;
2131+
2132+ // consumer: 2 own reducers, mounts auth
2133+ let mut consumer_builder = RawModuleDefV10Builder :: new ( ) ;
2134+ consumer_builder. add_reducer ( "consumer_a" , ProductType :: unit ( ) ) ;
2135+ consumer_builder. add_reducer ( "consumer_b" , ProductType :: unit ( ) ) ;
2136+ let mut consumer_raw = consumer_builder. finish ( ) ;
2137+ consumer_raw. sections . push ( RawModuleDefV10Section :: Mounts ( vec ! [ RawModuleMountV10 {
2138+ namespace: "auth" . to_string( ) ,
2139+ module: auth_raw,
2140+ } ] ) ) ;
2141+
2142+ let def: ModuleDef = consumer_raw. try_into ( ) . expect ( "valid module" ) ;
2143+
2144+ // Total count: 2 consumer + 1 auth + 1 baz
2145+ assert_eq ! ( def. reducer_count( ) , 4 ) ;
2146+
2147+ // Depth-first order: consumer_a=0, consumer_b=1, auth_verify=2, baz_reduce=3
2148+ let ids_and_defs = def. reducer_ids_and_defs ( ) ;
2149+ assert_eq ! ( ids_and_defs. len( ) , 4 ) ;
2150+ assert_eq ! ( ids_and_defs[ 0 ] . 0 , ReducerId ( 0 ) ) ;
2151+ assert_eq ! ( & * ids_and_defs[ 0 ] . 1 . name, "consumer_a" ) ;
2152+ assert_eq ! ( ids_and_defs[ 1 ] . 0 , ReducerId ( 1 ) ) ;
2153+ assert_eq ! ( & * ids_and_defs[ 1 ] . 1 . name, "consumer_b" ) ;
2154+ assert_eq ! ( ids_and_defs[ 2 ] . 0 , ReducerId ( 2 ) ) ;
2155+ assert_eq ! ( & * ids_and_defs[ 2 ] . 1 . name, "auth_verify" ) ;
2156+ assert_eq ! ( ids_and_defs[ 3 ] . 0 , ReducerId ( 3 ) ) ;
2157+ assert_eq ! ( & * ids_and_defs[ 3 ] . 1 . name, "baz_reduce" ) ;
2158+
2159+ // get_reducer_by_id resolves mounted reducer IDs correctly
2160+ assert_eq ! ( & * def. reducer_by_id( ReducerId ( 2 ) ) . name, "auth_verify" ) ;
2161+ assert_eq ! ( & * def. reducer_by_id( ReducerId ( 3 ) ) . name, "baz_reduce" ) ;
2162+ assert ! ( def. get_reducer_by_id( ReducerId ( 4 ) ) . is_none( ) ) ;
2163+
2164+ // reducer_by_name routes plain names to own reducers
2165+ let ( id, rdef) = def. reducer_by_name ( "consumer_a" ) . expect ( "plain name resolves" ) ;
2166+ assert_eq ! ( id, ReducerId ( 0 ) ) ;
2167+ assert_eq ! ( & * rdef. name, "consumer_a" ) ;
2168+
2169+ // reducer_by_name routes qualified names to mounted reducers
2170+ let ( id, rdef) = def. reducer_by_name ( "auth/auth_verify" ) . expect ( "qualified name resolves" ) ;
2171+ assert_eq ! ( id, ReducerId ( 2 ) ) ;
2172+ assert_eq ! ( & * rdef. name, "auth_verify" ) ;
2173+
2174+ // reducer_by_name routes deeply nested qualified names
2175+ let ( id, rdef) = def
2176+ . reducer_by_name ( "auth/baz/baz_reduce" )
2177+ . expect ( "nested qualified name resolves" ) ;
2178+ assert_eq ! ( id, ReducerId ( 3 ) ) ;
2179+ assert_eq ! ( & * rdef. name, "baz_reduce" ) ;
2180+
2181+ // Non-existent names return None
2182+ assert ! ( def. reducer_by_name( "auth/nonexistent" ) . is_none( ) ) ;
2183+ assert ! ( def. reducer_by_name( "nonexistent" ) . is_none( ) ) ;
2184+ assert ! ( def. reducer_by_name( "nonamespace/auth_verify" ) . is_none( ) ) ;
2185+ }
21122186}
0 commit comments