Tokio test: simulate clock

I'm trying to test a scenario involving timeout which resembles the following function - a receiver wait for a message, if no message received, it times out and send a message mentioning "Nothing"; echo otherwise.

async fn sample_task(timeout: u64, tx: Sender<String>, mut rx: Receiver<String>) {
    let result = tokio::time::timeout(Duration::from_millis(timeout/2),rx.recv()).await;
    println!("timed out");
    if let Ok(Some(msg)) = result {
    } else{

I tried the following test case to simulate the scenario.

async fn test_time_simulation() {
    let timeout:u64 = 100;
    let (tx_to_test, mut rx_from_task) = channel(10);
    let (tx,rx)=channel(10);
    tokio::spawn(sample_task(timeout,tx_to_test.clone(), rx));

    let result = tokio::time::timeout(Duration::from_millis(10),rx_from_task.recv()).await;

As no message is sent to rx, my understanding is to get timeout at tokio::time::timeout(Duration::from_millis(timeout),rx.recv()).await; after advance(..) and I'll get message "Nothing" from rx_from_task. But getting timeout instead during test (at tokio::time::timeout(Duration::from_millis(10),rx_from_task.recv()).await;).

What did I do wrong? Or is there any other way to achieve that?
Thanks in advance.


Interestingly, if I use the same value for advance(..) and timeout, the test passes. Playground

I think the problem here is that the advance happens before the spawned task starts executing. I don't really know why the version without /2 works though. It is fixable by adding yield_now().await; after the spawn, before the call to advance.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.