about summary refs log tree commit diff
diff options
context:
space:
mode:
authorzhuyunxing <zhuyunxing.zyx@alibaba-inc.com>2024-04-19 10:58:42 +0800
committerDeltalice <deltalice@outlook.com>2024-04-20 00:34:40 +0800
commit402dc38d99767e7e73896587be42ade438148151 (patch)
tree481cd48a3d124929646bd2a07710132a666f6871
parent439dbfa1ecb1b45db0acc728094d6e8ed3dc3080 (diff)
downloadrust-402dc38d99767e7e73896587be42ade438148151.tar.gz
rust-402dc38d99767e7e73896587be42ade438148151.zip
coverage. Add basic tests for MC/DC
-rw-r--r--tests/coverage/mcdc_if.cov-map218
-rw-r--r--tests/coverage/mcdc_if.coverage262
-rw-r--r--tests/coverage/mcdc_if.rs103
3 files changed, 583 insertions, 0 deletions
diff --git a/tests/coverage/mcdc_if.cov-map b/tests/coverage/mcdc_if.cov-map
new file mode 100644
index 00000000000..35a265684d2
--- /dev/null
+++ b/tests/coverage/mcdc_if.cov-map
@@ -0,0 +1,218 @@
+Function name: mcdc_if::mcdc_check_a
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 0f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 4
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
+- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+Number of file 0 mappings: 8
+- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9)
+- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
+- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
+    true  = c1
+    false = (c0 - c1)
+- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
+- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
+    true  = c3
+    false = c2
+- Code(Counter(3)) at (prev + 0, 15) to (start + 2, 6)
+- Code(Expression(3, Add)) at (prev + 2, 12) to (start + 2, 6)
+    = (c2 + (c0 - c1))
+- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2)
+    = (c3 + (c2 + (c0 - c1)))
+
+Function name: mcdc_if::mcdc_check_b
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 17, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 4
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
+- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+Number of file 0 mappings: 8
+- Code(Counter(0)) at (prev + 23, 1) to (start + 1, 9)
+- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
+- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
+    true  = c1
+    false = (c0 - c1)
+- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
+- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
+    true  = c3
+    false = c2
+- Code(Counter(3)) at (prev + 0, 15) to (start + 2, 6)
+- Code(Expression(3, Add)) at (prev + 2, 12) to (start + 2, 6)
+    = (c2 + (c0 - c1))
+- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2)
+    = (c3 + (c2 + (c0 - c1)))
+
+Function name: mcdc_if::mcdc_check_both
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 1f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 4
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
+- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+Number of file 0 mappings: 8
+- Code(Counter(0)) at (prev + 31, 1) to (start + 1, 9)
+- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
+- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
+    true  = c1
+    false = (c0 - c1)
+- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
+- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
+    true  = c3
+    false = c2
+- Code(Counter(3)) at (prev + 0, 15) to (start + 2, 6)
+- Code(Expression(3, Add)) at (prev + 2, 12) to (start + 2, 6)
+    = (c2 + (c0 - c1))
+- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2)
+    = (c3 + (c2 + (c0 - c1)))
+
+Function name: mcdc_if::mcdc_check_neither
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 07, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 4
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
+- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+Number of file 0 mappings: 8
+- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9)
+- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
+- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
+    true  = c1
+    false = (c0 - c1)
+- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
+- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
+    true  = c3
+    false = c2
+- Code(Counter(3)) at (prev + 0, 15) to (start + 2, 6)
+- Code(Expression(3, Add)) at (prev + 2, 12) to (start + 2, 6)
+    = (c2 + (c0 - c1))
+- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2)
+    = (c3 + (c2 + (c0 - c1)))
+
+Function name: mcdc_if::mcdc_check_not_tree_decision
+Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 31, 01, 03, 0a, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 8
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 3 operands: lhs = Counter(3), rhs = Expression(7, Sub)
+- expression 4 operands: lhs = Expression(0, Sub), rhs = Counter(2)
+- expression 5 operands: lhs = Counter(4), rhs = Expression(6, Add)
+- expression 6 operands: lhs = Counter(3), rhs = Expression(7, Sub)
+- expression 7 operands: lhs = Expression(0, Sub), rhs = Counter(2)
+Number of file 0 mappings: 10
+- Code(Counter(0)) at (prev + 49, 1) to (start + 3, 10)
+- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
+- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 3 } at (prev + 0, 9) to (start + 0, 10)
+    true  = c1
+    false = (c0 - c1)
+- Code(Expression(0, Sub)) at (prev + 0, 14) to (start + 0, 15)
+    = (c0 - c1)
+- MCDCBranch { true: Counter(2), false: Expression(7, Sub), condition_id: 3, true_next_id: 2, false_next_id: 0 } at (prev + 0, 14) to (start + 0, 15)
+    true  = c2
+    false = ((c0 - c1) - c2)
+- Code(Expression(2, Add)) at (prev + 0, 20) to (start + 0, 21)
+    = (c1 + c2)
+- MCDCBranch { true: Counter(4), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 20) to (start + 0, 21)
+    true  = c4
+    false = c3
+- Code(Counter(4)) at (prev + 0, 22) to (start + 2, 6)
+- Code(Expression(6, Add)) at (prev + 2, 12) to (start + 2, 6)
+    = (c3 + ((c0 - c1) - c2))
+- Code(Expression(5, Add)) at (prev + 3, 1) to (start + 0, 2)
+    = (c4 + (c3 + ((c0 - c1) - c2)))
+
+Function name: mcdc_if::mcdc_check_tree_decision
+Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 27, 01, 03, 09, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 8
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(1), rhs = Counter(3)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(3)
+- expression 3 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 4 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 5 operands: lhs = Expression(6, Add), rhs = Expression(7, Add)
+- expression 6 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 7 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+Number of file 0 mappings: 10
+- Code(Counter(0)) at (prev + 39, 1) to (start + 3, 9)
+- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
+- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
+    true  = c1
+    false = (c0 - c1)
+- Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15)
+- MCDCBranch { true: Counter(3), false: Expression(2, Sub), condition_id: 2, true_next_id: 0, false_next_id: 3 } at (prev + 0, 14) to (start + 0, 15)
+    true  = c3
+    false = (c1 - c3)
+- Code(Expression(2, Sub)) at (prev + 0, 19) to (start + 0, 20)
+    = (c1 - c3)
+- MCDCBranch { true: Counter(4), false: Counter(2), condition_id: 3, true_next_id: 0, false_next_id: 0 } at (prev + 0, 19) to (start + 0, 20)
+    true  = c4
+    false = c2
+- Code(Expression(6, Add)) at (prev + 0, 22) to (start + 2, 6)
+    = (c3 + c4)
+- Code(Expression(7, Add)) at (prev + 2, 12) to (start + 2, 6)
+    = (c2 + (c0 - c1))
+- Code(Expression(5, Add)) at (prev + 3, 1) to (start + 0, 2)
+    = ((c3 + c4) + (c2 + (c0 - c1)))
+
+Function name: mcdc_if::mcdc_nested_if
+Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 01, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 13
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 3 operands: lhs = Expression(6, Add), rhs = Counter(5)
+- expression 4 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(5)
+- expression 6 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 7 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 8 operands: lhs = Expression(0, Sub), rhs = Counter(2)
+- expression 9 operands: lhs = Expression(10, Add), rhs = Expression(12, Sub)
+- expression 10 operands: lhs = Counter(3), rhs = Expression(11, Add)
+- expression 11 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 12 operands: lhs = Expression(0, Sub), rhs = Counter(2)
+Number of file 0 mappings: 14
+- Code(Counter(0)) at (prev + 59, 1) to (start + 1, 9)
+- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
+- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 8) to (start + 0, 9)
+    true  = c1
+    false = (c0 - c1)
+- Code(Expression(0, Sub)) at (prev + 0, 13) to (start + 0, 14)
+    = (c0 - c1)
+- MCDCBranch { true: Counter(2), false: Expression(12, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
+    true  = c2
+    false = ((c0 - c1) - c2)
+- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 1, 13)
+    = (c1 + c2)
+- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 1, 12) to (start + 0, 18)
+- MCDCBranch { true: Expression(5, Sub), false: Counter(5), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 12) to (start + 0, 13)
+    true  = ((c1 + c2) - c5)
+    false = c5
+- Code(Expression(5, Sub)) at (prev + 0, 17) to (start + 0, 18)
+    = ((c1 + c2) - c5)
+- MCDCBranch { true: Counter(3), false: Counter(4), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 17) to (start + 0, 18)
+    true  = c3
+    false = c4
+- Code(Counter(3)) at (prev + 0, 19) to (start + 2, 10)
+- Code(Expression(11, Add)) at (prev + 2, 10) to (start + 0, 11)
+    = (c4 + c5)
+- Code(Expression(12, Sub)) at (prev + 1, 12) to (start + 2, 6)
+    = ((c0 - c1) - c2)
+- Code(Expression(9, Add)) at (prev + 3, 1) to (start + 0, 2)
+    = ((c3 + (c4 + c5)) + ((c0 - c1) - c2))
+
diff --git a/tests/coverage/mcdc_if.coverage b/tests/coverage/mcdc_if.coverage
new file mode 100644
index 00000000000..c2ed311a5bc
--- /dev/null
+++ b/tests/coverage/mcdc_if.coverage
@@ -0,0 +1,262 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |//@ edition: 2021
+   LL|       |//@ min-llvm-version: 18
+   LL|       |//@ compile-flags: -Zcoverage-options=mcdc
+   LL|       |//@ llvm-cov-flags: --show-mcdc
+   LL|       |
+   LL|      2|fn mcdc_check_neither(a: bool, b: bool) {
+   LL|      2|    if a && b {
+                          ^0
+  ------------------
+  |---> MC/DC Decision Region (LL:8) to (LL:14)
+  |
+  |  Number of Conditions: 2
+  |     Condition C1 --> (LL:8)
+  |     Condition C2 --> (LL:13)
+  |
+  |  Executed MC/DC Test Vectors:
+  |
+  |     C1, C2    Result
+  |  1 { F,  -  = F      }
+  |
+  |  C1-Pair: not covered
+  |  C2-Pair: not covered
+  |  MC/DC Coverage for Decision: 0.00%
+  |
+  ------------------
+   LL|      0|        say("a and b");
+   LL|      2|    } else {
+   LL|      2|        say("not both");
+   LL|      2|    }
+   LL|      2|}
+   LL|       |
+   LL|      2|fn mcdc_check_a(a: bool, b: bool) {
+   LL|      2|    if a && b {
+                          ^1
+  ------------------
+  |---> MC/DC Decision Region (LL:8) to (LL:14)
+  |
+  |  Number of Conditions: 2
+  |     Condition C1 --> (LL:8)
+  |     Condition C2 --> (LL:13)
+  |
+  |  Executed MC/DC Test Vectors:
+  |
+  |     C1, C2    Result
+  |  1 { F,  -  = F      }
+  |  2 { T,  T  = T      }
+  |
+  |  C1-Pair: covered: (1,2)
+  |  C2-Pair: not covered
+  |  MC/DC Coverage for Decision: 50.00%
+  |
+  ------------------
+   LL|      1|        say("a and b");
+   LL|      1|    } else {
+   LL|      1|        say("not both");
+   LL|      1|    }
+   LL|      2|}
+   LL|       |
+   LL|      2|fn mcdc_check_b(a: bool, b: bool) {
+   LL|      2|    if a && b {
+  ------------------
+  |---> MC/DC Decision Region (LL:8) to (LL:14)
+  |
+  |  Number of Conditions: 2
+  |     Condition C1 --> (LL:8)
+  |     Condition C2 --> (LL:13)
+  |
+  |  Executed MC/DC Test Vectors:
+  |
+  |     C1, C2    Result
+  |  1 { T,  F  = F      }
+  |  2 { T,  T  = T      }
+  |
+  |  C1-Pair: not covered
+  |  C2-Pair: covered: (1,2)
+  |  MC/DC Coverage for Decision: 50.00%
+  |
+  ------------------
+   LL|      1|        say("a and b");
+   LL|      1|    } else {
+   LL|      1|        say("not both");
+   LL|      1|    }
+   LL|      2|}
+   LL|       |
+   LL|      3|fn mcdc_check_both(a: bool, b: bool) {
+   LL|      3|    if a && b {
+                          ^2
+  ------------------
+  |---> MC/DC Decision Region (LL:8) to (LL:14)
+  |
+  |  Number of Conditions: 2
+  |     Condition C1 --> (LL:8)
+  |     Condition C2 --> (LL:13)
+  |
+  |  Executed MC/DC Test Vectors:
+  |
+  |     C1, C2    Result
+  |  1 { F,  -  = F      }
+  |  2 { T,  F  = F      }
+  |  3 { T,  T  = T      }
+  |
+  |  C1-Pair: covered: (1,3)
+  |  C2-Pair: covered: (2,3)
+  |  MC/DC Coverage for Decision: 100.00%
+  |
+  ------------------
+   LL|      1|        say("a and b");
+   LL|      2|    } else {
+   LL|      2|        say("not both");
+   LL|      2|    }
+   LL|      3|}
+   LL|       |
+   LL|      4|fn mcdc_check_tree_decision(a: bool, b: bool, c: bool) {
+   LL|      4|    // This expression is intentionally written in a way
+   LL|      4|    // where 100% branch coverage indicates 100% mcdc coverage.
+   LL|      4|    if a && (b || c) {
+                           ^3   ^2
+  ------------------
+  |---> MC/DC Decision Region (LL:8) to (LL:21)
+  |
+  |  Number of Conditions: 3
+  |     Condition C1 --> (LL:8)
+  |     Condition C2 --> (LL:14)
+  |     Condition C3 --> (LL:19)
+  |
+  |  Executed MC/DC Test Vectors:
+  |
+  |     C1, C2, C3    Result
+  |  1 { F,  -,  -  = F      }
+  |  2 { T,  F,  F  = F      }
+  |  3 { T,  T,  -  = T      }
+  |  4 { T,  F,  T  = T      }
+  |
+  |  C1-Pair: covered: (1,3)
+  |  C2-Pair: covered: (2,3)
+  |  C3-Pair: covered: (2,4)
+  |  MC/DC Coverage for Decision: 100.00%
+  |
+  ------------------
+   LL|      2|        say("pass");
+   LL|      2|    } else {
+   LL|      2|        say("reject");
+   LL|      2|    }
+   LL|      4|}
+   LL|       |
+   LL|      4|fn mcdc_check_not_tree_decision(a: bool, b: bool, c: bool) {
+   LL|      4|    // Contradict to `mcdc_check_tree_decision`,
+   LL|      4|    // 100% branch coverage of this expression does not mean indicates 100% mcdc coverage.
+   LL|      4|    if (a || b) && c {
+                           ^1
+  ------------------
+  |---> MC/DC Decision Region (LL:8) to (LL:21)
+  |
+  |  Number of Conditions: 3
+  |     Condition C1 --> (LL:9)
+  |     Condition C2 --> (LL:14)
+  |     Condition C3 --> (LL:20)
+  |
+  |  Executed MC/DC Test Vectors:
+  |
+  |     C1, C2, C3    Result
+  |  1 { T,  -,  F  = F      }
+  |  2 { T,  -,  T  = T      }
+  |  3 { F,  T,  T  = T      }
+  |
+  |  C1-Pair: not covered
+  |  C2-Pair: not covered
+  |  C3-Pair: covered: (1,2)
+  |  MC/DC Coverage for Decision: 33.33%
+  |
+  ------------------
+   LL|      2|        say("pass");
+   LL|      2|    } else {
+   LL|      2|        say("reject");
+   LL|      2|    }
+   LL|      4|}
+   LL|       |
+   LL|      3|fn mcdc_nested_if(a: bool, b: bool, c: bool) {
+   LL|      3|    if a || b {
+                          ^0
+  ------------------
+  |---> MC/DC Decision Region (LL:8) to (LL:14)
+  |
+  |  Number of Conditions: 2
+  |     Condition C1 --> (LL:8)
+  |     Condition C2 --> (LL:13)
+  |
+  |  Executed MC/DC Test Vectors:
+  |
+  |     C1, C2    Result
+  |  1 { T,  -  = T      }
+  |
+  |  C1-Pair: not covered
+  |  C2-Pair: not covered
+  |  MC/DC Coverage for Decision: 0.00%
+  |
+  ------------------
+   LL|      3|        say("a or b");
+   LL|      3|        if b && c {
+                              ^2
+  ------------------
+  |---> MC/DC Decision Region (LL:12) to (LL:18)
+  |
+  |  Number of Conditions: 2
+  |     Condition C1 --> (LL:12)
+  |     Condition C2 --> (LL:17)
+  |
+  |  Executed MC/DC Test Vectors:
+  |
+  |     C1, C2    Result
+  |  1 { F,  -  = F      }
+  |  2 { T,  F  = F      }
+  |  3 { T,  T  = T      }
+  |
+  |  C1-Pair: covered: (1,3)
+  |  C2-Pair: covered: (2,3)
+  |  MC/DC Coverage for Decision: 100.00%
+  |
+  ------------------
+   LL|      1|            say("b and c");
+   LL|      2|        }
+   LL|      0|    } else {
+   LL|      0|        say("neither a nor b");
+   LL|      0|    }
+   LL|      3|}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn main() {
+   LL|       |    mcdc_check_neither(false, false);
+   LL|       |    mcdc_check_neither(false, true);
+   LL|       |
+   LL|       |    mcdc_check_a(true, true);
+   LL|       |    mcdc_check_a(false, true);
+   LL|       |
+   LL|       |    mcdc_check_b(true, true);
+   LL|       |    mcdc_check_b(true, false);
+   LL|       |
+   LL|       |    mcdc_check_both(false, true);
+   LL|       |    mcdc_check_both(true, true);
+   LL|       |    mcdc_check_both(true, false);
+   LL|       |
+   LL|       |    mcdc_check_tree_decision(false, true, true);
+   LL|       |    mcdc_check_tree_decision(true, true, false);
+   LL|       |    mcdc_check_tree_decision(true, false, false);
+   LL|       |    mcdc_check_tree_decision(true, false, true);
+   LL|       |
+   LL|       |    mcdc_check_not_tree_decision(false, true, true);
+   LL|       |    mcdc_check_not_tree_decision(true, true, false);
+   LL|       |    mcdc_check_not_tree_decision(true, false, false);
+   LL|       |    mcdc_check_not_tree_decision(true, false, true);
+   LL|       |
+   LL|       |    mcdc_nested_if(true, false, true);
+   LL|       |    mcdc_nested_if(true, true, true);
+   LL|       |    mcdc_nested_if(true, true, false);
+   LL|       |}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn say(message: &str) {
+   LL|       |    core::hint::black_box(message);
+   LL|       |}
+
diff --git a/tests/coverage/mcdc_if.rs b/tests/coverage/mcdc_if.rs
new file mode 100644
index 00000000000..a85843721c6
--- /dev/null
+++ b/tests/coverage/mcdc_if.rs
@@ -0,0 +1,103 @@
+#![feature(coverage_attribute)]
+//@ edition: 2021
+//@ min-llvm-version: 18
+//@ compile-flags: -Zcoverage-options=mcdc
+//@ llvm-cov-flags: --show-mcdc
+
+fn mcdc_check_neither(a: bool, b: bool) {
+    if a && b {
+        say("a and b");
+    } else {
+        say("not both");
+    }
+}
+
+fn mcdc_check_a(a: bool, b: bool) {
+    if a && b {
+        say("a and b");
+    } else {
+        say("not both");
+    }
+}
+
+fn mcdc_check_b(a: bool, b: bool) {
+    if a && b {
+        say("a and b");
+    } else {
+        say("not both");
+    }
+}
+
+fn mcdc_check_both(a: bool, b: bool) {
+    if a && b {
+        say("a and b");
+    } else {
+        say("not both");
+    }
+}
+
+fn mcdc_check_tree_decision(a: bool, b: bool, c: bool) {
+    // This expression is intentionally written in a way
+    // where 100% branch coverage indicates 100% mcdc coverage.
+    if a && (b || c) {
+        say("pass");
+    } else {
+        say("reject");
+    }
+}
+
+fn mcdc_check_not_tree_decision(a: bool, b: bool, c: bool) {
+    // Contradict to `mcdc_check_tree_decision`,
+    // 100% branch coverage of this expression does not mean indicates 100% mcdc coverage.
+    if (a || b) && c {
+        say("pass");
+    } else {
+        say("reject");
+    }
+}
+
+fn mcdc_nested_if(a: bool, b: bool, c: bool) {
+    if a || b {
+        say("a or b");
+        if b && c {
+            say("b and c");
+        }
+    } else {
+        say("neither a nor b");
+    }
+}
+
+#[coverage(off)]
+fn main() {
+    mcdc_check_neither(false, false);
+    mcdc_check_neither(false, true);
+
+    mcdc_check_a(true, true);
+    mcdc_check_a(false, true);
+
+    mcdc_check_b(true, true);
+    mcdc_check_b(true, false);
+
+    mcdc_check_both(false, true);
+    mcdc_check_both(true, true);
+    mcdc_check_both(true, false);
+
+    mcdc_check_tree_decision(false, true, true);
+    mcdc_check_tree_decision(true, true, false);
+    mcdc_check_tree_decision(true, false, false);
+    mcdc_check_tree_decision(true, false, true);
+
+    mcdc_check_not_tree_decision(false, true, true);
+    mcdc_check_not_tree_decision(true, true, false);
+    mcdc_check_not_tree_decision(true, false, false);
+    mcdc_check_not_tree_decision(true, false, true);
+
+    mcdc_nested_if(true, false, true);
+    mcdc_nested_if(true, true, true);
+    mcdc_nested_if(true, true, false);
+}
+
+#[coverage(off)]
+fn say(message: &str) {
+    core::hint::black_box(message);
+}