@@ -97,3 +97,125 @@ impl<M: RawMutex, C, R> Request<'_, M, C, R> {
9797 self . channel . response . signal ( ( response, self . request_id ) ) ;
9898 }
9999}
100+
101+ #[ cfg( test) ]
102+ mod tests {
103+ use super :: * ;
104+ use embassy_sync:: blocking_mutex:: raw:: CriticalSectionRawMutex ;
105+ use embassy_sync:: once_lock:: OnceLock ;
106+ use tokio:: time:: Duration ;
107+
108+ #[ test]
109+ fn test_autoincrement ( ) {
110+ let channel = Channel :: < CriticalSectionRawMutex , u32 , u32 > :: new ( ) ;
111+ for i in 0 ..100 {
112+ let id = channel. get_next_request_id ( ) ;
113+ assert_eq ! ( id. 0 , i) ;
114+ }
115+ }
116+
117+ /// Mock commands
118+ #[ derive( Debug ) ]
119+ enum Command {
120+ A ,
121+ B ,
122+ C ,
123+ }
124+
125+ /// Mock responses
126+ #[ derive( Debug , PartialEq ) ]
127+ enum Response {
128+ A ,
129+ B ,
130+ C ,
131+ }
132+
133+ /// Mock command handler
134+ struct Handler {
135+ channel : Channel < CriticalSectionRawMutex , Command , Response > ,
136+ }
137+
138+ impl Handler {
139+ /// Create a new handler
140+ fn new ( ) -> Self {
141+ Self {
142+ channel : Channel :: new ( ) ,
143+ }
144+ }
145+
146+ /// Process a command and return a response
147+ async fn process_request ( & self , request : & Command ) -> Response {
148+ match request {
149+ Command :: A => Response :: A ,
150+ Command :: B => Response :: B ,
151+ Command :: C => {
152+ // Request that takes a while to finish
153+ tokio:: time:: sleep ( Duration :: from_millis ( 1000 ) ) . await ;
154+ Response :: C
155+ }
156+ }
157+ }
158+
159+ /// Send command A
160+ async fn send_a ( & self ) -> Response {
161+ self . channel . execute ( Command :: A ) . await
162+ }
163+
164+ /// Invoke command B
165+ async fn send_b ( & self ) -> Response {
166+ self . channel . execute ( Command :: B ) . await
167+ }
168+
169+ /// Invoke command C
170+ async fn send_c ( & self ) -> Response {
171+ self . channel . execute ( Command :: C ) . await
172+ }
173+
174+ /// Main processing task
175+ async fn process ( & self ) {
176+ loop {
177+ let request = self . channel . receive ( ) . await ;
178+ let response = self . process_request ( & request. command ) . await ;
179+ request. respond ( response) ;
180+ }
181+ }
182+ }
183+
184+ /// Task that executes command C followed by command A
185+ async fn task_0 ( handler : & ' static Handler ) {
186+ let response = tokio:: time:: timeout ( Duration :: from_millis ( 250 ) , handler. send_c ( ) ) . await ;
187+ // Tokio's timeout error value has a private constructor so is_err is the best we can do
188+ assert ! ( response. is_err( ) ) ;
189+
190+ let response = handler. send_a ( ) . await ;
191+ assert_eq ! ( response, Response :: A ) ;
192+ }
193+
194+ /// Task that executes command B
195+ async fn task_1 ( handler : & ' static Handler ) {
196+ let response = handler. send_b ( ) . await ;
197+ assert_eq ! ( response, Response :: B ) ;
198+ }
199+
200+ /// Task that handles device commands
201+ async fn handler_task ( handler : & ' static Handler ) {
202+ loop {
203+ handler. process ( ) . await ;
204+ }
205+ }
206+
207+ /// Test the command execution and response handling
208+ #[ tokio:: test]
209+ async fn test_send_receive ( ) {
210+ static DEVICE : OnceLock < Handler > = OnceLock :: new ( ) ;
211+
212+ let device = DEVICE . get_or_init ( Handler :: new) ;
213+ let _handler = tokio:: spawn ( handler_task ( device) ) ;
214+ let handle_0 = tokio:: spawn ( task_0 ( device) ) ;
215+ let handle_1 = tokio:: spawn ( task_1 ( device) ) ;
216+
217+ // Wait for invokers to finish
218+ handle_0. await . unwrap ( ) ;
219+ handle_1. await . unwrap ( ) ;
220+ }
221+ }
0 commit comments