@@ -72,6 +72,58 @@ def test_registry(self):
7272 # find_instance must return the existing instance
7373 self .assertEqual (can .Notifier .find_instances (bus ), (notifier ,))
7474
75+ def test_restart (self ):
76+ with can .Bus ("test" , interface = "virtual" , receive_own_messages = True ) as bus :
77+ reader = can .BufferedReader ()
78+ notifier = can .Notifier (bus , [reader ], 0.1 )
79+
80+ bus .send (can .Message (arbitration_id = 0x123 ))
81+ self .assertIsNotNone (reader .get_message (1 ))
82+
83+ notifier .stop ()
84+ self .assertTrue (notifier .stopped )
85+
86+ new_reader = can .BufferedReader ()
87+ notifier .listeners = [new_reader ]
88+
89+ notifier .restart ()
90+ self .assertFalse (notifier .stopped )
91+
92+ # Small settling time for the thread to actually start
93+ time .sleep (0.2 )
94+
95+ # Send and Verify
96+ msg = can .Message (arbitration_id = 0xABC )
97+ bus .send (msg )
98+
99+ recv = new_reader .get_message (1 )
100+ self .assertIsNotNone (recv , "Failed to receive message after restart" )
101+ self .assertEqual (recv .arbitration_id , 0xABC )
102+
103+ notifier .stop ()
104+
105+ def test_restart_registry_lifecycle (self ):
106+ with can .Bus ("test" , interface = "virtual" , receive_own_messages = True ) as bus :
107+ notifier = can .Notifier (bus , [], 0.1 )
108+ notifier .stop ()
109+
110+ # Verify it is removed from registry
111+ self .assertEqual (can .Notifier .find_instances (bus ), ())
112+
113+ notifier .restart ()
114+
115+ # Verify it is back in the registry and blocking others
116+ self .assertEqual (can .Notifier .find_instances (bus ), (notifier ,))
117+ self .assertRaises (ValueError , can .Notifier , bus , [], 0.1 )
118+
119+ notifier .stop ()
120+
121+ def test_double_restart_warning (self ):
122+ with can .Bus ("test" , interface = "virtual" , receive_own_messages = True ) as bus :
123+ with can .Notifier (bus , [], 0.1 ) as notifier :
124+ # Attempting to restart an already running notifier should warn
125+ with self .assertRaises (RuntimeWarning ):
126+ notifier .restart ()
75127
76128class AsyncNotifierTest (unittest .TestCase ):
77129 def test_asyncio_notifier (self ):
@@ -88,6 +140,36 @@ async def run_it():
88140
89141 asyncio .run (run_it ())
90142
143+ def test_asyncio_notifier_restart (self ):
144+ async def run_it ():
145+ with can .Bus ("test" , interface = "virtual" , receive_own_messages = True ) as bus :
146+ reader = can .AsyncBufferedReader ()
147+ notifier = can .Notifier (
148+ bus , [reader ], 0.1 , loop = asyncio .get_running_loop ()
149+ )
150+
151+ notifier .stop ()
152+
153+ # In some cases, creating a new listener is the safest path for a restart
154+ new_reader = can .AsyncBufferedReader ()
155+ notifier .listeners = [new_reader ]
156+
157+ notifier .restart ()
158+
159+ # Small yield to let the selector register the FD
160+ await asyncio .sleep (0.1 )
161+
162+ bus .send (can .Message (arbitration_id = 0x123 ))
163+
164+ recv_msg = await asyncio .wait_for (new_reader .get_message (), 1.5 )
165+
166+ self .assertIsNotNone (recv_msg )
167+ self .assertEqual (recv_msg .arbitration_id , 0x123 )
168+
169+ notifier .stop ()
170+
171+ asyncio .run (run_it ())
172+
91173
92174if __name__ == "__main__" :
93175 unittest .main ()
0 commit comments