About #[tokio::test]
#[tokio::test] 运行时
#[tokio::test] 运行时和 #[tokio::main] 的默认值是不一样的,前者默认单线程,后者默认多线程:
The default test runtime is single-threaded.
所以有的时候运行和测试的结果可能不同。
可以设置为多线程的风格:
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn my_test() {
    assert!(true);
}
如何不同?
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn test() {
    let rc = std::sync::Arc::new(tokio::sync::Mutex::new(false));
    let executed = rc.clone();
    let mut join_handle = tokio::spawn(async move {
        println!("task running");
        *executed.lock().await = true;
        std::future::pending::<()>().await;
    });
    let executed = rc.clone();
    assert!(!*executed.lock().await); // 一般来说,就算是多线程环境下 task 也还没能运行
    // let _ = tokio::task::yield_now().await; // 在单线程下,必须主动 await 释放执行权,task 才能被安排运行
    join_handle.abort();
    assert!((&mut join_handle).await.unwrap_err().is_cancelled());
}
搞啰嗦了,简单点:
#[tokio::test]
async fn test() {
    let rc = std::sync::Arc::new(tokio::sync::Mutex::new(false));
    let executed = rc.clone();
    let join_handle = tokio::spawn(async move {
        println!("task running");
        *executed.lock().await = true;
        std::future::pending::<()>().await;
    });
    let executed = rc.clone();
    loop {
        let v = *executed.lock().await;
        println!("{v}");
        sleep(2000).await;
    }
}
// 输出:
running 1 test
false
task running
true
true
这段代码如果没有对锁进行 await,那么在单线程下的输出不可能是 true。(致敬不确定性原理、AKA 测不准原理)
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
#[tokio::test(flavor = "multi_thread", worker_threads = 1)] 真的是单线程的吗?不是,因为下面两个测试都会执行task:
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn test() {
    let rc = std::sync::Arc::new(tokio::sync::Mutex::new(false));
    let executed = rc.clone();
    let join_handle = tokio::spawn(async move {
        println!("task running");
        *executed.lock().await = true;
        std::future::pending::<()>().await;
    });
    std::thread::sleep(std::time::Duration::from_millis(8000));
}
#[tokio::test]
async fn test() {
    let rc = std::sync::Arc::new(tokio::sync::Mutex::new(false));
    let executed = rc.clone();
    let join_handle = tokio::spawn(async move {
        println!("task running");
        *executed.lock().await = true;
        std::future::pending::<()>().await;
    });
    let _ = tokio::task::yield_now().await;
    std::thread::sleep(std::time::Duration::from_millis(4000));
}
所以说 worker_threads 是指除了调度器主线程以外的工作线程数量,也就是说 flavor = "multi_thread" 至少会产生两个线程。
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号