@@ -98,3 +98,60 @@ impl ClientManager {
9898 self . clients . lock ( ) . remove ( id) ;
9999 }
100100}
101+
102+ #[ cfg( test) ]
103+ mod tests {
104+ use super :: * ;
105+
106+ #[ test]
107+ fn register_client_tracks_active_session ( ) {
108+ let mgr = Arc :: new ( ClientManager :: new ( ) ) ;
109+ let mut client = APIClient :: default ( ) ;
110+ client. session_id = "session-1" . to_string ( ) ;
111+ let client = Arc :: new ( client) ;
112+
113+ let mgr_clone = Arc :: clone ( & mgr) ;
114+ let client_clone = Arc :: clone ( & client) ;
115+ GLOBAL_RUNTIME . block_on ( async move {
116+ mgr_clone. register_client ( client_clone) . await ;
117+ } ) ;
118+
119+ {
120+ let guard = mgr. clients . lock ( ) ;
121+ let stored = guard. get ( "session-1" ) . expect ( "client not stored" ) ;
122+ assert ! (
123+ stored. upgrade( ) . is_some( ) ,
124+ "stored weak reference is dangling"
125+ ) ;
126+ assert_eq ! ( guard. len( ) , 1 ) ;
127+ }
128+
129+ drop ( client) ;
130+ let guard = mgr. clients . lock ( ) ;
131+ let stored = guard. get ( "session-1" ) . expect ( "client missing after drop" ) ;
132+ assert ! (
133+ stored. upgrade( ) . is_none( ) ,
134+ "weak reference should be cleared after client drop"
135+ ) ;
136+ }
137+
138+ #[ test]
139+ fn unregister_client_removes_session ( ) {
140+ let mgr = Arc :: new ( ClientManager :: new ( ) ) ;
141+ let mut client = APIClient :: default ( ) ;
142+ client. session_id = "session-2" . to_string ( ) ;
143+ let client = Arc :: new ( client) ;
144+
145+ let mgr_clone = Arc :: clone ( & mgr) ;
146+ let client_clone = Arc :: clone ( & client) ;
147+ GLOBAL_RUNTIME . block_on ( async move {
148+ mgr_clone. register_client ( client_clone) . await ;
149+ } ) ;
150+
151+ mgr. unregister_client ( "session-2" ) ;
152+ assert ! (
153+ !mgr. clients. lock( ) . contains_key( "session-2" ) ,
154+ "client entry should be removed after unregister"
155+ ) ;
156+ }
157+ }
0 commit comments