@@ -6,6 +6,8 @@ use libcoap_rs::{CoapContext, CoapRequestHandler, CoapResource};
66use std:: net:: { SocketAddr , UdpSocket } ;
77use std:: rc:: Rc ;
88use std:: sync:: atomic:: { AtomicBool , Ordering } ;
9+ use std:: sync:: { Arc , Condvar , Mutex } ;
10+ use std:: thread:: JoinHandle ;
911use std:: time:: Duration ;
1012
1113pub ( crate ) fn get_unused_server_addr ( ) -> SocketAddr {
@@ -25,6 +27,39 @@ pub(crate) fn get_unused_server_addr() -> SocketAddr {
2527 . expect ( "Failed to get server socket address" )
2628}
2729
30+ /// Spawns a test server in a new thread and waits for context_configurator to complete before
31+ /// returning.
32+ /// As the context_configurator closure is responsible for binding to sockets, this can be used to
33+ /// spawn a test server and wait for it to be ready to accept requests before returning (avoiding
34+ /// test failure due to "Connection Refused" errors).
35+ pub ( crate ) fn spawn_test_server < F : FnOnce ( & mut CoapContext ) + Send + ' static > (
36+ context_configurator : F ,
37+ ) -> JoinHandle < ( ) > {
38+ let ready_condition = Arc :: new ( ( Mutex :: new ( false ) , Condvar :: new ( ) ) ) ;
39+ let ready_condition2 = Arc :: clone ( & ready_condition) ;
40+
41+ let server_handle = std:: thread:: spawn ( move || {
42+ let ( ready_var, ready_cond) = & * ready_condition2;
43+ run_test_server ( |context| {
44+ context_configurator ( context) ;
45+ let mut ready_var = ready_var. lock ( ) . expect ( "ready condition mutex is poisoned" ) ;
46+ * ready_var = true ;
47+ ready_cond. notify_all ( ) ;
48+ } ) ;
49+ } ) ;
50+
51+ let ( ready_var, ready_cond) = & * ready_condition;
52+ drop (
53+ ready_cond
54+ . wait_while ( ready_var. lock ( ) . expect ( "ready condition mutex is poisoned" ) , |ready| {
55+ !* ready
56+ } )
57+ . expect ( "ready condition mutex is poisoned" ) ,
58+ ) ;
59+ server_handle
60+ }
61+
62+ /// Configures and starts a test server in the current thread.
2863pub ( crate ) fn run_test_server < F : FnOnce ( & mut CoapContext ) > ( context_configurator : F ) {
2964 let mut context = CoapContext :: new ( ) . unwrap ( ) ;
3065 context_configurator ( & mut context) ;
0 commit comments