More improvements to macro coverage

This commit is contained in:
Rich Kadel 2021-04-26 16:27:54 -07:00
parent c26afb765c
commit f12795f8a0
7 changed files with 366 additions and 155 deletions

View file

@ -1,9 +1,9 @@
1| |#![allow(unused_assignments, unused_variables, dead_code)]
2| |
3| 1|fn main() {
4| | // Initialize test constants in a way that cannot be determined at compile time, to ensure
5| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
6| | // dependent conditions.
4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
6| 1| // dependent conditions.
7| 1| let is_true = std::env::args().len() == 1;
8| 1|
9| 1| let mut countdown = 0;

View file

@ -1,17 +1,17 @@
1| |// FIXME(#84561): function-like macros produce unintuitive coverage results.
2| |// This test demonstrates some of the problems.
3| |
4| 18|#[derive(Debug, PartialEq, Eq)]
^5 ^0
1| |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
2| |
3| |// expect-exit-status-101
4| 21|#[derive(PartialEq, Eq)]
^0
------------------
| <issue_84561::Foo as core::cmp::PartialEq>::eq:
| 4| 18|#[derive(Debug, PartialEq, Eq)]
| 4| 21|#[derive(PartialEq, Eq)]
------------------
| Unexecuted instantiation: <issue_84561::Foo as core::cmp::PartialEq>::ne
------------------
5| |struct Foo(u32);
6| |
7| 1|fn main() {
6| 1|fn test2() {
7| 1| let is_true = std::env::args().len() == 1;
8| 1| let bar = Foo(1);
9| 1| assert_eq!(bar, Foo(1));
10| 1| let baz = Foo(0);
@ -23,80 +23,158 @@
16| 1| assert_eq!(Foo(1), Foo(1));
17| 1| assert_ne!(Foo(0), Foo(1));
18| 1| assert_eq!(Foo(2), Foo(2));
19| 1| let bar = Foo(1);
20| 1| assert_ne!(Foo(0), Foo(3));
19| 1| let bar = Foo(0);
20| 1| assert_ne!(bar, Foo(3));
21| 1| assert_ne!(Foo(0), Foo(4));
22| 1| assert_eq!(Foo(3), Foo(3));
23| 1| assert_ne!(Foo(0), Foo(5));
24| 1| println!("{:?}", bar);
25| 1| println!("{:?}", Foo(1));
26| 1|
27| 1| let is_true = std::env::args().len() == 1;
28| 1|
29| 1| assert_eq!(
30| 1| Foo(1),
31| 1| Foo(1)
32| 1| );
33| 1| assert_ne!(
34| 1| Foo(0),
35| 1| Foo(1)
36| 1| );
37| 1| assert_eq!(
38| 1| Foo(2),
39| 1| Foo(2)
40| 1| );
41| 1| let bar = Foo(1
42| 1| );
43| 1| assert_ne!(
44| 1| Foo(0),
45| 1| Foo(3)
46| 1| );
47| 1| if is_true {
48| 1| assert_ne!(
49| 1| Foo(0),
50| 1| Foo(4)
51| 1| );
52| | } else {
53| 0| assert_eq!(
54| 0| Foo(3),
55| 0| Foo(3)
56| 0| );
57| | }
58| | assert_ne!(
59| 1| if is_true {
60| 1| Foo(0)
61| | } else {
62| 0| Foo(1)
63| | },
64| | Foo(5)
65| | );
66| 1| assert_ne!(
67| 1| Foo(5),
68| 1| if is_true {
69| 1| Foo(0)
70| | } else {
71| 0| Foo(1)
72| | }
73| | );
74| | assert_ne!(
75| 1| if is_true {
76| 1| assert_eq!(
77| 1| Foo(3),
78| 1| Foo(3)
79| 1| );
80| 1| Foo(0)
81| | } else {
82| | assert_ne!(
83| 0| if is_true {
84| 0| Foo(0)
85| | } else {
86| 0| Foo(1)
87| | },
88| | Foo(5)
89| | );
22| 1| assert_eq!(Foo(3), Foo(3), "with a message");
^0
23| 1| println!("{:?}", bar);
24| 1| println!("{:?}", Foo(1));
25| 1|
26| 1| assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
^0 ^0 ^0
27| 1| assert_ne!(
28| | Foo(0)
29| | ,
30| | Foo(5)
31| | ,
32| 0| "{}"
33| 0| ,
34| 0| if
35| 0| is_true
36| | {
37| 0| "true message"
38| | } else {
39| 0| "false message"
40| | }
41| | );
42| |
43| 1| let is_true = std::env::args().len() == 1;
44| 1|
45| 1| assert_eq!(
46| 1| Foo(1),
47| 1| Foo(1)
48| 1| );
49| 1| assert_ne!(
50| 1| Foo(0),
51| 1| Foo(1)
52| 1| );
53| 1| assert_eq!(
54| 1| Foo(2),
55| 1| Foo(2)
56| 1| );
57| 1| let bar = Foo(1);
58| 1| assert_ne!(
59| 1| bar,
60| 1| Foo(3)
61| 1| );
62| 1| if is_true {
63| 1| assert_ne!(
64| 1| Foo(0),
65| 1| Foo(4)
66| 1| );
67| | } else {
68| 0| assert_eq!(
69| 0| Foo(3),
70| 0| Foo(3)
71| 0| );
72| | }
73| 1| if is_true {
74| 1| assert_ne!(
75| | Foo(0),
76| | Foo(4),
77| 0| "with a message"
78| | );
79| | } else {
80| 0| assert_eq!(
81| | Foo(3),
82| | Foo(3),
83| 0| "with a message"
84| | );
85| | }
86| 1| assert_ne!(
87| 1| if is_true {
88| 1| Foo(0)
89| | } else {
90| 0| Foo(1)
91| | },
92| | Foo(5)
93| | );
94| 1|}
94| 1| assert_ne!(
95| 1| Foo(5),
96| 1| if is_true {
97| 1| Foo(0)
98| | } else {
99| 0| Foo(1)
100| | }
101| | );
102| 1| assert_ne!(
103| 1| if is_true {
104| 1| assert_eq!(
105| 1| Foo(3),
106| 1| Foo(3)
107| 1| );
108| 1| Foo(0)
109| | } else {
110| 0| assert_ne!(
111| 0| if is_true {
112| 0| Foo(0)
113| | } else {
114| 0| Foo(1)
115| | },
116| | Foo(5)
117| | );
118| 0| Foo(1)
119| | },
120| | Foo(5),
121| 0| "with a message"
122| | );
123| 1| assert_eq!(
124| | Foo(1),
125| | Foo(3),
126| 1| "this assert should fail"
127| | );
128| 0| assert_eq!(
129| | Foo(3),
130| | Foo(3),
131| 0| "this assert should not be reached"
132| | );
133| 0|}
134| |
135| |impl std::fmt::Debug for Foo {
136| | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
137| 7| write!(f, "try and succeed")?;
^0
138| 7| Ok(())
139| 7| }
140| |}
141| |
142| |static mut DEBUG_LEVEL_ENABLED: bool = false;
143| |
144| |macro_rules! debug {
145| | ($($arg:tt)+) => (
146| | if unsafe { DEBUG_LEVEL_ENABLED } {
147| | println!($($arg)+);
148| | }
149| | );
150| |}
151| |
152| 1|fn test1() {
153| 1| debug!("debug is enabled");
^0
154| 1| debug!("debug is enabled");
^0
155| 1| let _ = 0;
156| 1| debug!("debug is enabled");
^0
157| 1| unsafe {
158| 1| DEBUG_LEVEL_ENABLED = true;
159| 1| }
160| 1| debug!("debug is enabled");
161| 1|}
162| |
163| 1|fn main() {
164| 1| test1();
165| 1| test2();
166| 1|}

View file

@ -3,9 +3,9 @@
3| |use std::fmt::Debug;
4| |
5| 1|pub fn used_function() {
6| | // Initialize test constants in a way that cannot be determined at compile time, to ensure
7| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
8| | // dependent conditions.
6| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
7| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
8| 1| // dependent conditions.
9| 1| let is_true = std::env::args().len() == 1;
10| 1| let mut countdown = 0;
11| 1| if is_true {

View file

@ -5,9 +5,9 @@
5| |use std::fmt::Debug;
6| |
7| 1|pub fn used_function() {
8| | // Initialize test constants in a way that cannot be determined at compile time, to ensure
9| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
10| | // dependent conditions.
8| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
9| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
10| 1| // dependent conditions.
11| 1| let is_true = std::env::args().len() == 1;
12| 1| let mut countdown = 0;
13| 1| if is_true {
@ -19,9 +19,9 @@
18| |
19| |#[inline(always)]
20| 1|pub fn used_inline_function() {
21| | // Initialize test constants in a way that cannot be determined at compile time, to ensure
22| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
23| | // dependent conditions.
21| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
22| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
23| 1| // dependent conditions.
24| 1| let is_true = std::env::args().len() == 1;
25| 1| let mut countdown = 0;
26| 1| if is_true {

View file

@ -1,10 +1,10 @@
// FIXME(#84561): function-like macros produce unintuitive coverage results.
// This test demonstrates some of the problems.
// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
#[derive(Debug, PartialEq, Eq)]
// expect-exit-status-101
#[derive(PartialEq, Eq)]
struct Foo(u32);
fn main() {
fn test2() {
let is_true = std::env::args().len() == 1;
let bar = Foo(1);
assert_eq!(bar, Foo(1));
let baz = Foo(0);
@ -16,14 +16,30 @@ fn main() {
assert_eq!(Foo(1), Foo(1));
assert_ne!(Foo(0), Foo(1));
assert_eq!(Foo(2), Foo(2));
let bar = Foo(1);
assert_ne!(Foo(0), Foo(3));
let bar = Foo(0);
assert_ne!(bar, Foo(3));
assert_ne!(Foo(0), Foo(4));
assert_eq!(Foo(3), Foo(3));
assert_ne!(Foo(0), Foo(5));
assert_eq!(Foo(3), Foo(3), "with a message");
println!("{:?}", bar);
println!("{:?}", Foo(1));
assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
assert_ne!(
Foo(0)
,
Foo(5)
,
"{}"
,
if
is_true
{
"true message"
} else {
"false message"
}
);
let is_true = std::env::args().len() == 1;
assert_eq!(
@ -38,10 +54,9 @@ fn main() {
Foo(2),
Foo(2)
);
let bar = Foo(1
);
let bar = Foo(1);
assert_ne!(
Foo(0),
bar,
Foo(3)
);
if is_true {
@ -55,6 +70,19 @@ fn main() {
Foo(3)
);
}
if is_true {
assert_ne!(
Foo(0),
Foo(4),
"with a message"
);
} else {
assert_eq!(
Foo(3),
Foo(3),
"with a message"
);
}
assert_ne!(
if is_true {
Foo(0)
@ -89,6 +117,50 @@ fn main() {
);
Foo(1)
},
Foo(5)
Foo(5),
"with a message"
);
assert_eq!(
Foo(1),
Foo(3),
"this assert should fail"
);
assert_eq!(
Foo(3),
Foo(3),
"this assert should not be reached"
);
}
impl std::fmt::Debug for Foo {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "try and succeed")?;
Ok(())
}
}
static mut DEBUG_LEVEL_ENABLED: bool = false;
macro_rules! debug {
($($arg:tt)+) => (
if unsafe { DEBUG_LEVEL_ENABLED } {
println!($($arg)+);
}
);
}
fn test1() {
debug!("debug is enabled");
debug!("debug is enabled");
let _ = 0;
debug!("debug is enabled");
unsafe {
DEBUG_LEVEL_ENABLED = true;
}
debug!("debug is enabled");
}
fn main() {
test1();
test2();
}