2023-12-15 05:38:27 +00:00
|
|
|
LL| |#![feature(coverage_attribute)]
|
2024-01-16 02:40:01 +00:00
|
|
|
LL| |#![feature(custom_inner_attributes)] // for #![rustfmt::skip]
|
2023-12-15 05:38:27 +00:00
|
|
|
LL| |#![feature(noop_waker)]
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| |#![allow(unused_assignments, dead_code)]
|
2024-01-16 02:40:01 +00:00
|
|
|
LL| |#![rustfmt::skip]
|
2023-12-15 05:38:27 +00:00
|
|
|
LL| |//@ edition: 2018
|
|
|
|
LL| |//@ compile-flags: -Copt-level=1
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| |
|
|
|
|
LL| 1|async fn c(x: u8) -> u8 {
|
|
|
|
LL| 1| if x == 8 {
|
|
|
|
LL| 1| 1
|
|
|
|
LL| | } else {
|
|
|
|
LL| 0| 0
|
|
|
|
LL| | }
|
|
|
|
LL| 1|}
|
|
|
|
LL| |
|
|
|
|
LL| 0|async fn d() -> u8 { 1 }
|
|
|
|
LL| |
|
|
|
|
LL| 0|async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
|
|
|
|
LL| |
|
|
|
|
LL| 1|async fn f() -> u8 { 1 }
|
|
|
|
LL| |
|
|
|
|
LL| 0|async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
|
|
|
|
LL| |
|
|
|
|
LL| 1|pub async fn g(x: u8) {
|
|
|
|
LL| 0| match x {
|
|
|
|
LL| 0| y if e().await == y => (),
|
|
|
|
LL| 0| y if f().await == y => (),
|
|
|
|
LL| 0| _ => (),
|
|
|
|
LL| | }
|
|
|
|
LL| 0|}
|
|
|
|
LL| |
|
|
|
|
LL| 1|async fn h(x: usize) { // The function signature is counted when called, but the body is not
|
|
|
|
LL| 0| // executed (not awaited) so the open brace has a `0` count (at least when
|
|
|
|
LL| 0| // displayed with `llvm-cov show` in color-mode).
|
|
|
|
LL| 0| match x {
|
|
|
|
LL| 0| y if foo().await[y] => (),
|
|
|
|
LL| 0| _ => (),
|
|
|
|
LL| | }
|
|
|
|
LL| 0|}
|
|
|
|
LL| |
|
|
|
|
LL| 1|async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
|
|
|
|
LL| 1| // (a) the function signature, counted when the function is called; and
|
|
|
|
LL| 1| // (b) the open brace for the function body, counted once when the body is
|
|
|
|
LL| 1| // executed asynchronously.
|
|
|
|
LL| 1| match x {
|
|
|
|
LL| 1| y if c(x).await == y + 1 => { d().await; }
|
2024-09-05 22:25:25 +00:00
|
|
|
^0 ^0
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| 1| y if f().await == y + 1 => (),
|
2024-09-05 22:25:25 +00:00
|
|
|
^0 ^0
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| 1| _ => (),
|
|
|
|
LL| | }
|
|
|
|
LL| 1|}
|
|
|
|
LL| |
|
|
|
|
LL| 1|fn j(x: u8) {
|
2024-07-01 03:29:54 +00:00
|
|
|
LL| | // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| 1| fn c(x: u8) -> u8 {
|
|
|
|
LL| 1| if x == 8 {
|
2024-07-01 03:29:54 +00:00
|
|
|
LL| 0| 1
|
|
|
|
LL| | } else {
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| 1| 0
|
2024-07-01 03:29:54 +00:00
|
|
|
LL| | }
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| 1| }
|
2024-07-01 03:29:54 +00:00
|
|
|
LL| 0| fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| 1| fn f() -> u8 { 1 }
|
|
|
|
LL| 1| match x {
|
|
|
|
LL| 1| y if c(x) == y + 1 => { d(); }
|
2020-12-01 07:58:08 +00:00
|
|
|
^0 ^0
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| 1| y if f() == y + 1 => (),
|
2020-12-01 07:58:08 +00:00
|
|
|
^0 ^0
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| 1| _ => (),
|
|
|
|
LL| | }
|
|
|
|
LL| 1|}
|
|
|
|
LL| |
|
|
|
|
LL| 0|fn k(x: u8) { // unused function
|
|
|
|
LL| 0| match x {
|
|
|
|
LL| 0| 1 => (),
|
|
|
|
LL| 0| 2 => (),
|
|
|
|
LL| 0| _ => (),
|
|
|
|
LL| | }
|
|
|
|
LL| 0|}
|
|
|
|
LL| |
|
|
|
|
LL| 1|fn l(x: u8) {
|
|
|
|
LL| 1| match x {
|
|
|
|
LL| 0| 1 => (),
|
|
|
|
LL| 0| 2 => (),
|
|
|
|
LL| 1| _ => (),
|
|
|
|
LL| | }
|
|
|
|
LL| 1|}
|
|
|
|
LL| |
|
|
|
|
LL| 1|async fn m(x: u8) -> u8 { x - 1 }
|
2020-12-02 07:01:26 +00:00
|
|
|
^0
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| |
|
|
|
|
LL| 1|fn main() {
|
|
|
|
LL| 1| let _ = g(10);
|
|
|
|
LL| 1| let _ = h(9);
|
|
|
|
LL| 1| let mut future = Box::pin(i(8));
|
|
|
|
LL| 1| j(7);
|
|
|
|
LL| 1| l(6);
|
|
|
|
LL| 1| let _ = m(5);
|
|
|
|
LL| 1| executor::block_on(future.as_mut());
|
|
|
|
LL| 1|}
|
|
|
|
LL| |
|
|
|
|
LL| |mod executor {
|
2023-12-15 05:38:27 +00:00
|
|
|
LL| | use core::future::Future;
|
|
|
|
LL| | use core::pin::pin;
|
|
|
|
LL| | use core::task::{Context, Poll, Waker};
|
|
|
|
LL| |
|
|
|
|
LL| | #[coverage(off)]
|
|
|
|
LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output {
|
|
|
|
LL| | let mut future = pin!(future);
|
2024-01-15 00:25:43 +00:00
|
|
|
LL| | let mut context = Context::from_waker(Waker::noop());
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| |
|
|
|
|
LL| | loop {
|
2023-12-15 05:38:27 +00:00
|
|
|
LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
|
|
|
|
LL| | break val;
|
|
|
|
LL| | }
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| | }
|
2023-12-15 05:38:27 +00:00
|
|
|
LL| | }
|
2023-08-16 02:42:33 +00:00
|
|
|
LL| |}
|
Coverage tests for remaining TerminatorKinds and async, improve Assert
Tested and validate results for panic unwind, panic abort, assert!()
macro, TerminatorKind::Assert (for example, numeric overflow), and
async/await.
Implemented a previous documented idea to change Assert handling to be
the same as FalseUnwind and Goto, so it doesn't get its own
BasicCoverageBlock anymore. This changed a couple of coverage regions,
but I validated those changes are not any worse than the prior results,
and probably help assure some consistency (even if some people might
disagree with how the code region is consistently computed).
Fixed issue with async/await. AggregateKind::Generator needs to be
handled like AggregateKind::Closure; coverage span for the outer async
function should not "cover" the async body, which is actually executed
in a separate "closure" MIR.
2020-11-16 17:14:28 +00:00
|
|
|
|