@@ -98,3 +98,54 @@ 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 ! ( stored. upgrade( ) . is_some( ) , "stored weak reference is dangling" ) ;
123+ assert_eq ! ( guard. len( ) , 1 ) ;
124+ }
125+
126+ drop ( client) ;
127+ let guard = mgr. clients . lock ( ) ;
128+ let stored = guard. get ( "session-1" ) . expect ( "client missing after drop" ) ;
129+ assert ! ( stored. upgrade( ) . is_none( ) , "weak reference should be cleared after client drop" ) ;
130+ }
131+
132+ #[ test]
133+ fn unregister_client_removes_session ( ) {
134+ let mgr = Arc :: new ( ClientManager :: new ( ) ) ;
135+ let mut client = APIClient :: default ( ) ;
136+ client. session_id = "session-2" . to_string ( ) ;
137+ let client = Arc :: new ( client) ;
138+
139+ let mgr_clone = Arc :: clone ( & mgr) ;
140+ let client_clone = Arc :: clone ( & client) ;
141+ GLOBAL_RUNTIME . block_on ( async move {
142+ mgr_clone. register_client ( client_clone) . await ;
143+ } ) ;
144+
145+ mgr. unregister_client ( "session-2" ) ;
146+ assert ! (
147+ !mgr. clients. lock( ) . contains_key( "session-2" ) ,
148+ "client entry should be removed after unregister"
149+ ) ;
150+ }
151+ }
0 commit comments