Skip to content

async closures are incorrectly marked as not covered #459

@lukaslihotzki-f

Description

@lukaslihotzki-f

When using an async closure as an endpoint handler in axum, its body is completely marked as not covered, even though it is executed. In the following example, the lines 14 and 15 from the async closure are marked as not covered, while the lines 5 and 6 from the async fn are correctly marked as covered.

Example:

use axum::{Router, routing::get};
use tokio::net::TcpListener;

async fn async_fn_endpoint() -> axum::http::StatusCode {
    println!("Called async fn!");
    axum::http::StatusCode::OK
}

fn router() -> Router {
    Router::new()
        .route(
            "/async_closure",
            get(async || {
                println!("Called async closure!");
                axum::http::StatusCode::OK
            }),
        )
        .route("/async_fn", get(async_fn_endpoint))
}

pub async fn serve(listener: TcpListener) -> Result<(), std::io::Error> {
    axum::serve(listener, router()).await
}

#[cfg(test)]
mod tests {
    use tokio::net::TcpListener;

    #[tokio::test]
    async fn test() {
        let listener = TcpListener::bind(std::net::SocketAddrV6::new(
            std::net::Ipv6Addr::LOCALHOST,
            0,
            0,
            0,
        ))
        .await
        .unwrap();
        let local_addr = listener.local_addr().unwrap();

        tokio::spawn(crate::serve(listener));

        let client = reqwest::Client::new();

        for endpoint in ["async_closure", "async_fn"] {
            let url = format!("http://{}/{}", local_addr, endpoint);
            let response = client.get(url).send().await.unwrap();
            assert_eq!(response.status(), 200);
        }
    }
}

When running the test with cargo llvm-cov nextest --workspace --lcov --output-path lcov.info --no-capture && genhtml lcov.info -o html, the output indicates that both endpoint handlers were actually called:

running 1 test
Called async closure!
Called async fn!
test tests::test ... ok

These are the dependencies:

[dependencies]
axum = "0.7"
tokio = "1.0"

[dev-dependencies]
reqwest = "0.11"

This may be an issue of the underlying code coverage support in Rust, but I'm not sure, so I decided to file the issue in the user-facing project first.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions