-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Code coverage misses .await
lines
#98712
Comments
Playing around, it seems that the
With the My guess is that only the "bail out to the calling frame" logic has a BCB counter in it (or maybe there simply is no code in the other branch to count) so unless the future yields the counter is not incremented, and the span is deemed unhit. |
Does anyone have a suggestion on how to re-write the example so it could be used as a helper-type or function to actually get code coverage on I am trying to do something like this: async_func().await; would become Yield::new(async_func()).await But, my rust futures abilities aren't so strong. I'll keep at it, and post something if I figure it out. |
I did write a workaround that works for my needs. https://github.com/cameronelliott/await-coverage-workaround.git I created a helper type, so now I do This will fix the coverage where the await is invoked. The helper type doesn't get 100% coverage, and it may be possible to |
Since I sometimes clean my repos, I will add the workaround right here! use std::future::Future;
#[allow(dead_code)]
#[derive(Debug, Default)]
struct Yield {
init: bool,
}
impl std::future::Future for Yield {
type Output = ();
fn poll(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
if !self.init {
self.init = true;
cx.waker().wake_by_ref();
return std::task::Poll::Pending;
} else {
return std::task::Poll::Ready(());
}
}
}
trait FixCoverage {
async fn fix_cov(self) -> <Self as Future>::Output
where
Self: Sized,
Self: Future,
{
// this will NOT show as covered
// but for my usage I just keep it outside of my coverage checked code
let r = self.await;
Yield::default().await;
r
}
}
impl<F, T> FixCoverage for F where F: Future<Output = T> {}
pub async fn do_things() {
println!("Hello world");
}
#[tokio::main]
pub async fn main() {
do_things().await; // will NOT show as covered
do_things().fix_cov().await; // will show as covered
} |
Note that
|
Rollup merge of rust-lang#130013 - jonathan-conder:await_coverage, r=Zalathar coverage: Count await when the Future is immediately ready Currently `await` is only counted towards coverage if the containing function is suspended and resumed at least once. This is because it expands to code which contains a branch on the discriminant of `Poll`. By treating it like a branching macro (e.g. `assert!`), these implementation details will be hidden from the coverage results. I added a test to ensure the fix works in simple cases, but the heuristic of picking only the first await-related covspan might be unreliable. I plan on testing more thoroughly with a real codebase over the next couple of weeks. closes rust-lang#98712
I tried running the LLVM code coverage report against this code using
cargo llvm-cov
:I expected this to result in 100% code coverage.
Instead, the
.await
on line 3 is considered not covered:Meta
The text was updated successfully, but these errors were encountered: