about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZalathar <Zalathar@users.noreply.github.com>2024-04-17 12:32:11 +1000
committerZalathar <Zalathar@users.noreply.github.com>2024-04-22 21:55:33 +1000
commit3de87feba23c6b9df520f284b51390c02ea8d12a (patch)
tree395d094e40d7cdb8f9cc50619e537697c917247e
parent7f432dfb23f264f5c368464f849663a518750a93 (diff)
downloadrust-3de87feba23c6b9df520f284b51390c02ea8d12a.tar.gz
rust-3de87feba23c6b9df520f284b51390c02ea8d12a.zip
coverage: Branch coverage tests for match arms
-rw-r--r--tests/coverage/branch/match-arms.cov-map92
-rw-r--r--tests/coverage/branch/match-arms.coverage105
-rw-r--r--tests/coverage/branch/match-arms.rs90
-rw-r--r--tests/coverage/branch/match-trivial.cov-map17
-rw-r--r--tests/coverage/branch/match-trivial.coverage49
-rw-r--r--tests/coverage/branch/match-trivial.rs48
6 files changed, 401 insertions, 0 deletions
diff --git a/tests/coverage/branch/match-arms.cov-map b/tests/coverage/branch/match-arms.cov-map
new file mode 100644
index 00000000000..1f17f11baaa
--- /dev/null
+++ b/tests/coverage/branch/match-arms.cov-map
@@ -0,0 +1,92 @@
+Function name: match_arms::guards
+Raw bytes (88): 0x[01, 01, 08, 07, 15, 0b, 11, 0f, 0d, 00, 09, 17, 25, 1b, 21, 1f, 1d, 03, 19, 0c, 01, 30, 01, 01, 10, 29, 03, 0b, 00, 10, 19, 01, 11, 00, 29, 20, 19, 09, 00, 17, 00, 1b, 1d, 01, 11, 00, 29, 20, 1d, 0d, 00, 17, 00, 1b, 21, 01, 11, 00, 29, 20, 21, 11, 00, 17, 00, 1b, 25, 01, 11, 00, 29, 20, 25, 15, 00, 17, 00, 1b, 03, 01, 0e, 00, 18, 13, 03, 05, 01, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 8
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(5)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(4)
+- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(3)
+- expression 3 operands: lhs = Zero, rhs = Counter(2)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(9)
+- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(8)
+- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(7)
+- expression 7 operands: lhs = Expression(0, Add), rhs = Counter(6)
+Number of file 0 mappings: 12
+- Code(Counter(0)) at (prev + 48, 1) to (start + 1, 16)
+- Code(Counter(10)) at (prev + 3, 11) to (start + 0, 16)
+- Code(Counter(6)) at (prev + 1, 17) to (start + 0, 41)
+- Branch { true: Counter(6), false: Counter(2) } at (prev + 0, 23) to (start + 0, 27)
+    true  = c6
+    false = c2
+- Code(Counter(7)) at (prev + 1, 17) to (start + 0, 41)
+- Branch { true: Counter(7), false: Counter(3) } at (prev + 0, 23) to (start + 0, 27)
+    true  = c7
+    false = c3
+- Code(Counter(8)) at (prev + 1, 17) to (start + 0, 41)
+- Branch { true: Counter(8), false: Counter(4) } at (prev + 0, 23) to (start + 0, 27)
+    true  = c8
+    false = c4
+- Code(Counter(9)) at (prev + 1, 17) to (start + 0, 41)
+- Branch { true: Counter(9), false: Counter(5) } at (prev + 0, 23) to (start + 0, 27)
+    true  = c9
+    false = c5
+- Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 24)
+    = ((((Zero + c2) + c3) + c4) + c5)
+- Code(Expression(4, Add)) at (prev + 3, 5) to (start + 1, 2)
+    = ((((((((Zero + c2) + c3) + c4) + c5) + c6) + c7) + c8) + c9)
+
+Function name: match_arms::match_arms
+Raw bytes (51): 0x[01, 01, 06, 05, 07, 0b, 11, 09, 0d, 13, 02, 17, 09, 11, 0d, 07, 01, 18, 01, 01, 10, 05, 03, 0b, 00, 10, 11, 01, 11, 00, 21, 0d, 01, 11, 00, 21, 09, 01, 11, 00, 21, 02, 01, 11, 00, 21, 0f, 03, 05, 01, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 6
+- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(4)
+- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 3 operands: lhs = Expression(4, Add), rhs = Expression(0, Sub)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(2)
+- expression 5 operands: lhs = Counter(4), rhs = Counter(3)
+Number of file 0 mappings: 7
+- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 16)
+- Code(Counter(1)) at (prev + 3, 11) to (start + 0, 16)
+- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 33)
+- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33)
+- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33)
+- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 33)
+    = (c1 - ((c2 + c3) + c4))
+- Code(Expression(3, Add)) at (prev + 3, 5) to (start + 1, 2)
+    = (((c4 + c3) + c2) + (c1 - ((c2 + c3) + c4)))
+
+Function name: match_arms::or_patterns
+Raw bytes (75): 0x[01, 01, 0d, 11, 0d, 05, 2f, 33, 11, 09, 0d, 09, 2a, 05, 2f, 33, 11, 09, 0d, 03, 27, 09, 2a, 05, 2f, 33, 11, 09, 0d, 09, 01, 25, 01, 01, 10, 05, 03, 0b, 00, 10, 11, 01, 11, 00, 12, 0d, 00, 1e, 00, 1f, 03, 00, 24, 00, 2e, 09, 01, 11, 00, 12, 2a, 00, 1e, 00, 1f, 27, 00, 24, 00, 2e, 23, 03, 05, 01, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 13
+- expression 0 operands: lhs = Counter(4), rhs = Counter(3)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(11, Add)
+- expression 2 operands: lhs = Expression(12, Add), rhs = Counter(4)
+- expression 3 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 4 operands: lhs = Counter(2), rhs = Expression(10, Sub)
+- expression 5 operands: lhs = Counter(1), rhs = Expression(11, Add)
+- expression 6 operands: lhs = Expression(12, Add), rhs = Counter(4)
+- expression 7 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 8 operands: lhs = Expression(0, Add), rhs = Expression(9, Add)
+- expression 9 operands: lhs = Counter(2), rhs = Expression(10, Sub)
+- expression 10 operands: lhs = Counter(1), rhs = Expression(11, Add)
+- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(4)
+- expression 12 operands: lhs = Counter(2), rhs = Counter(3)
+Number of file 0 mappings: 9
+- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 16)
+- Code(Counter(1)) at (prev + 3, 11) to (start + 0, 16)
+- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 18)
+- Code(Counter(3)) at (prev + 0, 30) to (start + 0, 31)
+- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 46)
+    = (c4 + c3)
+- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18)
+- Code(Expression(10, Sub)) at (prev + 0, 30) to (start + 0, 31)
+    = (c1 - ((c2 + c3) + c4))
+- Code(Expression(9, Add)) at (prev + 0, 36) to (start + 0, 46)
+    = (c2 + (c1 - ((c2 + c3) + c4)))
+- Code(Expression(8, Add)) at (prev + 3, 5) to (start + 1, 2)
+    = ((c4 + c3) + (c2 + (c1 - ((c2 + c3) + c4))))
+
diff --git a/tests/coverage/branch/match-arms.coverage b/tests/coverage/branch/match-arms.coverage
new file mode 100644
index 00000000000..ea8a6f97ab1
--- /dev/null
+++ b/tests/coverage/branch/match-arms.coverage
@@ -0,0 +1,105 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |//@ edition: 2021
+   LL|       |//@ compile-flags: -Zcoverage-options=branch
+   LL|       |//@ llvm-cov-flags: --show-branches=count
+   LL|       |
+   LL|       |// Tests for branch coverage of various kinds of match arms.
+   LL|       |
+   LL|       |// Helper macro to prevent start-of-function spans from being merged into
+   LL|       |// spans on the lines we care about.
+   LL|       |macro_rules! no_merge {
+   LL|       |    () => {
+   LL|       |        for _ in 0..1 {}
+   LL|       |    };
+   LL|       |}
+   LL|       |
+   LL|       |#[derive(Clone, Copy, Debug)]
+   LL|       |enum Enum {
+   LL|       |    A(u32),
+   LL|       |    B(u32),
+   LL|       |    C(u32),
+   LL|       |    D(u32),
+   LL|       |}
+   LL|       |
+   LL|     15|fn match_arms(value: Enum) {
+   LL|     15|    no_merge!();
+   LL|       |
+   LL|     15|    match value {
+   LL|      8|        Enum::D(d) => consume(d),
+   LL|      4|        Enum::C(c) => consume(c),
+   LL|      2|        Enum::B(b) => consume(b),
+   LL|      1|        Enum::A(a) => consume(a),
+   LL|       |    }
+   LL|       |
+   LL|     15|    consume(0);
+   LL|     15|}
+   LL|       |
+   LL|     15|fn or_patterns(value: Enum) {
+   LL|     15|    no_merge!();
+   LL|       |
+   LL|     15|    match value {
+   LL|     12|        Enum::D(x) | Enum::C(x) => consume(x),
+                              ^8           ^4
+   LL|      3|        Enum::B(y) | Enum::A(y) => consume(y),
+                              ^2           ^1
+   LL|       |    }
+   LL|       |
+   LL|     15|    consume(0);
+   LL|     15|}
+   LL|       |
+   LL|     45|fn guards(value: Enum, cond: bool) {
+   LL|     45|    no_merge!();
+   LL|       |
+   LL|      3|    match value {
+   LL|      8|        Enum::D(d) if cond => consume(d),
+  ------------------
+  |  Branch (LL:23): [True: 8, False: 16]
+  ------------------
+   LL|      4|        Enum::C(c) if cond => consume(c),
+  ------------------
+  |  Branch (LL:23): [True: 4, False: 8]
+  ------------------
+   LL|      2|        Enum::B(b) if cond => consume(b),
+  ------------------
+  |  Branch (LL:23): [True: 2, False: 4]
+  ------------------
+   LL|      1|        Enum::A(a) if cond => consume(a),
+  ------------------
+  |  Branch (LL:23): [True: 1, False: 2]
+  ------------------
+   LL|     30|        _ => consume(0),
+   LL|       |    }
+   LL|       |
+   LL|     45|    consume(0);
+   LL|     45|}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn consume<T>(x: T) {
+   LL|       |    core::hint::black_box(x);
+   LL|       |}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn main() {
+   LL|       |    #[coverage(off)]
+   LL|       |    fn call_everything(e: Enum) {
+   LL|       |        match_arms(e);
+   LL|       |        or_patterns(e);
+   LL|       |        for cond in [false, false, true] {
+   LL|       |            guards(e, cond);
+   LL|       |        }
+   LL|       |    }
+   LL|       |
+   LL|       |    call_everything(Enum::A(0));
+   LL|       |    for b in 0..2 {
+   LL|       |        call_everything(Enum::B(b));
+   LL|       |    }
+   LL|       |    for c in 0..4 {
+   LL|       |        call_everything(Enum::C(c));
+   LL|       |    }
+   LL|       |    for d in 0..8 {
+   LL|       |        call_everything(Enum::D(d));
+   LL|       |    }
+   LL|       |}
+   LL|       |
+   LL|       |// FIXME(#124118) Actually instrument match arms for branch coverage.
+
diff --git a/tests/coverage/branch/match-arms.rs b/tests/coverage/branch/match-arms.rs
new file mode 100644
index 00000000000..63151f59ffe
--- /dev/null
+++ b/tests/coverage/branch/match-arms.rs
@@ -0,0 +1,90 @@
+#![feature(coverage_attribute)]
+//@ edition: 2021
+//@ compile-flags: -Zcoverage-options=branch
+//@ llvm-cov-flags: --show-branches=count
+
+// Tests for branch coverage of various kinds of match arms.
+
+// Helper macro to prevent start-of-function spans from being merged into
+// spans on the lines we care about.
+macro_rules! no_merge {
+    () => {
+        for _ in 0..1 {}
+    };
+}
+
+#[derive(Clone, Copy, Debug)]
+enum Enum {
+    A(u32),
+    B(u32),
+    C(u32),
+    D(u32),
+}
+
+fn match_arms(value: Enum) {
+    no_merge!();
+
+    match value {
+        Enum::D(d) => consume(d),
+        Enum::C(c) => consume(c),
+        Enum::B(b) => consume(b),
+        Enum::A(a) => consume(a),
+    }
+
+    consume(0);
+}
+
+fn or_patterns(value: Enum) {
+    no_merge!();
+
+    match value {
+        Enum::D(x) | Enum::C(x) => consume(x),
+        Enum::B(y) | Enum::A(y) => consume(y),
+    }
+
+    consume(0);
+}
+
+fn guards(value: Enum, cond: bool) {
+    no_merge!();
+
+    match value {
+        Enum::D(d) if cond => consume(d),
+        Enum::C(c) if cond => consume(c),
+        Enum::B(b) if cond => consume(b),
+        Enum::A(a) if cond => consume(a),
+        _ => consume(0),
+    }
+
+    consume(0);
+}
+
+#[coverage(off)]
+fn consume<T>(x: T) {
+    core::hint::black_box(x);
+}
+
+#[coverage(off)]
+fn main() {
+    #[coverage(off)]
+    fn call_everything(e: Enum) {
+        match_arms(e);
+        or_patterns(e);
+        for cond in [false, false, true] {
+            guards(e, cond);
+        }
+    }
+
+    call_everything(Enum::A(0));
+    for b in 0..2 {
+        call_everything(Enum::B(b));
+    }
+    for c in 0..4 {
+        call_everything(Enum::C(c));
+    }
+    for d in 0..8 {
+        call_everything(Enum::D(d));
+    }
+}
+
+// FIXME(#124118) Actually instrument match arms for branch coverage.
diff --git a/tests/coverage/branch/match-trivial.cov-map b/tests/coverage/branch/match-trivial.cov-map
new file mode 100644
index 00000000000..1136a529b25
--- /dev/null
+++ b/tests/coverage/branch/match-trivial.cov-map
@@ -0,0 +1,17 @@
+Function name: match_trivial::_uninhabited (unused)
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 10]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Zero) at (prev + 22, 1) to (start + 1, 16)
+
+Function name: match_trivial::trivial
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 10, 05, 03, 0b, 05, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16)
+- Code(Counter(1)) at (prev + 3, 11) to (start + 5, 2)
+
diff --git a/tests/coverage/branch/match-trivial.coverage b/tests/coverage/branch/match-trivial.coverage
new file mode 100644
index 00000000000..4ffb172e1b6
--- /dev/null
+++ b/tests/coverage/branch/match-trivial.coverage
@@ -0,0 +1,49 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |//@ edition: 2021
+   LL|       |//@ compile-flags: -Zcoverage-options=branch
+   LL|       |//@ llvm-cov-flags: --show-branches=count
+   LL|       |
+   LL|       |// When instrumenting match expressions for branch coverage, make sure we don't
+   LL|       |// cause an ICE or produce weird coverage output for matches with <2 arms.
+   LL|       |
+   LL|       |// Helper macro to prevent start-of-function spans from being merged into
+   LL|       |// spans on the lines we care about.
+   LL|       |macro_rules! no_merge {
+   LL|       |    () => {
+   LL|       |        for _ in 0..1 {}
+   LL|       |    };
+   LL|       |}
+   LL|       |
+   LL|       |enum Uninhabited {}
+   LL|       |enum Trivial {
+   LL|       |    Value,
+   LL|       |}
+   LL|       |
+   LL|      0|fn _uninhabited(x: Uninhabited) {
+   LL|      0|    no_merge!();
+   LL|       |
+   LL|       |    match x {}
+   LL|       |
+   LL|       |    consume("done");
+   LL|       |}
+   LL|       |
+   LL|      1|fn trivial(x: Trivial) {
+   LL|      1|    no_merge!();
+   LL|       |
+   LL|      1|    match x {
+   LL|      1|        Trivial::Value => consume("trivial"),
+   LL|      1|    }
+   LL|      1|
+   LL|      1|    consume("done");
+   LL|      1|}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn consume<T>(x: T) {
+   LL|       |    core::hint::black_box(x);
+   LL|       |}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn main() {
+   LL|       |    trivial(Trivial::Value);
+   LL|       |}
+
diff --git a/tests/coverage/branch/match-trivial.rs b/tests/coverage/branch/match-trivial.rs
new file mode 100644
index 00000000000..db8887a26b7
--- /dev/null
+++ b/tests/coverage/branch/match-trivial.rs
@@ -0,0 +1,48 @@
+#![feature(coverage_attribute)]
+//@ edition: 2021
+//@ compile-flags: -Zcoverage-options=branch
+//@ llvm-cov-flags: --show-branches=count
+
+// When instrumenting match expressions for branch coverage, make sure we don't
+// cause an ICE or produce weird coverage output for matches with <2 arms.
+
+// Helper macro to prevent start-of-function spans from being merged into
+// spans on the lines we care about.
+macro_rules! no_merge {
+    () => {
+        for _ in 0..1 {}
+    };
+}
+
+enum Uninhabited {}
+enum Trivial {
+    Value,
+}
+
+fn _uninhabited(x: Uninhabited) {
+    no_merge!();
+
+    match x {}
+
+    consume("done");
+}
+
+fn trivial(x: Trivial) {
+    no_merge!();
+
+    match x {
+        Trivial::Value => consume("trivial"),
+    }
+
+    consume("done");
+}
+
+#[coverage(off)]
+fn consume<T>(x: T) {
+    core::hint::black_box(x);
+}
+
+#[coverage(off)]
+fn main() {
+    trivial(Trivial::Value);
+}