webrtc
webrtc copied to clipboard
Make tests that rely on time deterimnistic
There are many tests that use tokio::time::sleep
to advance time and observe the effect of timers/tickers running. This is brittle and flaky.
$ rg -g '**/*/*test.rs' sleep
data/src/data_channel/data_channel_test.rs: tokio::time::sleep(Duration::from_millis(10)).await;
data/src/data_channel/data_channel_test.rs: let timer = tokio::time::sleep(Duration::from_millis(10));
data/src/data_channel/data_channel_test.rs: let timer = tokio::time::sleep(Duration::from_millis(10));
data/src/data_channel/data_channel_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
data/src/data_channel/data_channel_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
data/src/data_channel/data_channel_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
data/src/data_channel/data_channel_test.rs: tokio::time::sleep(Duration::from_millis(10)).await;
sctp/src/timer/timer_test.rs:use tokio::time::{sleep, Duration};
sctp/src/timer/timer_test.rs: sleep(ACK_INTERVAL + Duration::from_millis(50)).await;
sctp/src/timer/timer_test.rs: sleep(Duration::from_millis(650)).await;
sctp/src/timer/timer_test.rs: sleep(Duration::from_millis((interval * 3) / 2)).await;
sctp/src/timer/timer_test.rs: sleep(Duration::from_millis((interval * 3) / 2)).await;
sctp/src/timer/timer_test.rs: sleep(Duration::from_millis((interval * 3) / 2)).await;
sctp/src/timer/timer_test.rs: sleep(Duration::from_millis(100)).await;
dtls/src/conn/conn_test.rs: tokio::time::sleep(Duration::from_millis(1)).await;
dtls/src/conn/conn_test.rs: tokio::time::sleep(Duration::from_millis(1)).await;
dtls/src/conn/conn_test.rs: tokio::time::sleep(Duration::from_millis(1)).await;
dtls/src/conn/conn_test.rs: let timer = tokio::time::sleep(Duration::from_millis(10));
dtls/src/conn/conn_test.rs: //tokio::time::sleep(Duration::from_millis(300)).await;
dtls/src/conn/conn_test.rs: tokio::time::sleep(Duration::from_millis(50)).await;
dtls/src/conn/conn_test.rs: tokio::time::sleep(Duration::from_millis(50)).await;
dtls/src/conn/conn_test.rs: tokio::time::sleep(Duration::from_millis(5)).await;
sctp/src/association/association_test.rs: let timer = tokio::time::sleep(Duration::from_millis(10));
sctp/src/association/association_test.rs: let timer = tokio::time::sleep(Duration::from_millis(10));
sctp/src/association/association_test.rs: tokio::time::sleep(Duration::from_millis(10)).await;
sctp/src/association/association_test.rs: tokio::time::sleep(Duration::from_millis(10)).await;
sctp/src/association/association_test.rs: tokio::time::sleep(Duration::from_millis(10)).await;
sctp/src/association/association_test.rs: tokio::time::sleep(Duration::from_millis(10)).await;
sctp/src/association/association_test.rs: tokio::time::sleep(Duration::from_millis(10)).await;
sctp/src/association/association_test.rs: tokio::time::sleep(Duration::from_millis(10)).await;
sctp/src/association/association_test.rs: tokio::time::sleep(Duration::from_millis(4)).await;
sctp/src/association/association_test.rs: let timer = tokio::time::sleep(Duration::from_millis(10));
sctp/src/association/association_test.rs: let timer = tokio::time::sleep(Duration::from_millis(10));
sctp/src/association/association_test.rs: let timer = tokio::time::sleep(Duration::from_millis(10));
sctp/src/association/association_test.rs: tokio::time::sleep(Duration::from_millis(10)).await;
sctp/src/association/association_test.rs: let timer1 = tokio::time::sleep(Duration::from_secs(1));
sctp/src/association/association_test.rs: let timer2 = tokio::time::sleep(Duration::from_secs(1));
sctp/src/association/association_test.rs: let timer2 = tokio::time::sleep(Duration::from_secs(1));
sctp/src/association/association_test.rs: tokio::time::sleep(Duration::from_millis(20)).await;
sctp/src/association/association_test.rs: let timer2 = tokio::time::sleep(Duration::from_secs(1));
sctp/src/association/association_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
interceptor/src/nack/generator/generator_test.rs: tokio::time::sleep(INTERVAL * 2).await; // wait for at least 2 nack packets
interceptor/src/twcc/receiver/receiver_test.rs: tokio::time::sleep(Duration::from_millis(*d)).await;
interceptor/src/twcc/receiver/receiver_test.rs: tokio::time::sleep(Duration::from_millis(*d)).await;
interceptor/src/twcc/sender/sender_test.rs: let timeout = tokio::time::sleep(Duration::from_millis(10));
webrtc/src/peer_connection/peer_connection_test.rs: let timeout = tokio::time::sleep(Duration::from_secs(10));
webrtc/src/peer_connection/peer_connection_test.rs: let timeout = tokio::time::sleep(Duration::from_millis(20));
webrtc/src/peer_connection/peer_connection_test.rs: tokio::time::sleep(Duration::from_secs(1)).await;
webrtc/src/ice_transport/ice_transport_test.rs: tokio::time::sleep(Duration::from_secs(1)).await;
webrtc/src/dtls_transport/dtls_transport_test.rs: let timeout = tokio::time::sleep(Duration::from_secs(1));
webrtc/src/data_channel/data_channel_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
webrtc/src/data_channel/data_channel_test.rs: tokio::time::sleep(Duration::from_millis(50)).await;
webrtc/src/data_channel/data_channel_test.rs: // randomly sleep
webrtc/src/data_channel/data_channel_test.rs: tokio::time::sleep(Duration::from_millis(r)).await;
webrtc/src/data_channel/data_channel_test.rs: // randomly sleep
webrtc/src/data_channel/data_channel_test.rs: tokio::time::sleep(Duration::from_millis(r)).await;
webrtc/src/data_channel/data_channel_test.rs: tokio::time::sleep(Duration::from_millis(10)).await;
webrtc/src/data_channel/data_channel_test.rs: tokio::time::sleep(Duration::from_millis(10)).await;
stun/src/agent/agent_test.rs: let timeout = tokio::time::sleep(Duration::from_millis(400));
util/src/buffer/buffer_test.rs:use tokio::time::{sleep, Duration};
util/src/buffer/buffer_test.rs: sleep(Duration::from_micros(1)).await;
util/src/buffer/buffer_test.rs: sleep(Duration::from_micros(1)).await;
util/src/conn/conn_udp_listener_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
util/src/conn/conn_udp_listener_test.rs: let timer = tokio::time::sleep(Duration::from_millis(10));
util/src/conn/conn_udp_listener_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
util/src/conn/conn_udp_listener_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
ice/src/agent/agent_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
ice/src/agent/agent_vnet_test.rs: tokio::time::sleep(Duration::from_secs(1)).await;
ice/src/agent/agent_vnet_test.rs: tokio::time::sleep(Duration::from_secs(1)).await;
ice/src/agent/agent_vnet_test.rs: tokio::time::sleep(Duration::from_secs(1)).await;
ice/src/agent/agent_vnet_test.rs: tokio::time::sleep(Duration::from_secs(1)).await;
ice/src/agent/agent_vnet_test.rs: tokio::time::sleep(Duration::from_secs(1)).await;
ice/src/agent/agent_vnet_test.rs: tokio::time::sleep(Duration::from_millis(20)).await;
ice/src/udp_mux/udp_mux_test.rs:use tokio::time::{sleep, timeout};
ice/src/udp_mux/udp_mux_test.rs: sleep(Duration::from_millis(1)).await;
ice/src/udp_mux/udp_mux_test.rs: sleep(Duration::from_millis(1)).await;
turn/src/allocation/allocation_manager/allocation_manager_test.rs: tokio::time::sleep(lifetime + Duration::from_millis(100)).await;
turn/src/allocation/allocation_manager/allocation_manager_test.rs: tokio::time::sleep(Duration::from_millis(150)).await;
util/src/vnet/nat/nat_test.rs: tokio::time::sleep(Duration::from_millis(5)).await;
util/src/vnet/nat/nat_test.rs: // sleep long enough for the mapping to expire
util/src/vnet/nat/nat_test.rs: tokio::time::sleep(Duration::from_millis(225)).await;
util/src/vnet/nat/nat_test.rs: // sleep long enough for the mapping to expire
util/src/vnet/nat/nat_test.rs: tokio::time::sleep(Duration::from_millis(125)).await;
util/src/vnet/router/router_test.rs: tokio::time::sleep(Duration::from_millis(50)).await;
util/src/vnet/router/router_test.rs: tokio::time::sleep(Duration::from_millis(50)).await;
turn/src/allocation/channel_bind/channel_bind_test.rs: tokio::time::sleep(Duration::from_millis(30)).await;
turn/src/allocation/channel_bind/channel_bind_test.rs: tokio::time::sleep(Duration::from_millis(20)).await;
turn/src/allocation/channel_bind/channel_bind_test.rs: tokio::time::sleep(Duration::from_millis(20)).await;
turn/src/client/periodic_timer/periodic_timer_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
turn/src/client/periodic_timer/periodic_timer_test.rs: tokio::time::sleep(Duration::from_millis(120)).await;
turn/src/server/server_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
turn/src/server/server_test.rs: tokio::time::sleep(Duration::from_millis(100)).await;
Remedy
Instead of using tokio::time::sleep
the underlying code should be refactored to be driven from the outseide or the tests refecatored to use tokio::time::advance
.
Advance
With tokio advance when a spawned task is using timeouts or tickers changed the code from
tokio::time::sleep(some_duration).await;
to
tokio::time::advance(some_duration).await;
tokio::task::yield_now().await;
and change the test attributed to
#[tokio::test(start_paused = true)]
async fn my_test() {
Example PR that fixes one of these issues: https://github.com/webrtc-rs/webrtc/pull/258
I fixed some more cases to do with TWCC in https://github.com/webrtc-rs/webrtc/pull/324