From acd6e4c0fd10ac356d2bddbf47595748d0e3f2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 3 May 2024 10:28:09 +0000 Subject: [PATCH 1/3] tests(coverage): Add mcdc_non_control_flow tests --- tests/coverage/mcdc_non_control_flow.cov-map | 199 ++++++++++++++++++ tests/coverage/mcdc_non_control_flow.coverage | 98 +++++++++ tests/coverage/mcdc_non_control_flow.rs | 72 +++++++ 3 files changed, 369 insertions(+) create mode 100644 tests/coverage/mcdc_non_control_flow.cov-map create mode 100644 tests/coverage/mcdc_non_control_flow.coverage create mode 100644 tests/coverage/mcdc_non_control_flow.rs diff --git a/tests/coverage/mcdc_non_control_flow.cov-map b/tests/coverage/mcdc_non_control_flow.cov-map new file mode 100644 index 0000000000000..3f422d85e7992 --- /dev/null +++ b/tests/coverage/mcdc_non_control_flow.cov-map @@ -0,0 +1,199 @@ +Function name: mcdc_non_control_flow::assign_3 +Raw bytes (73): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 09, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 22, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 20, 1e, 11, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 20, 09, 0d, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 9 +- 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 = Counter(0), rhs = Counter(1) +- expression 4 operands: lhs = Counter(0), rhs = Counter(1) +- expression 5 operands: lhs = Expression(8, Sub), rhs = Counter(4) +- expression 6 operands: lhs = Counter(0), rhs = Counter(1) +- expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(4) +- expression 8 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 40) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = (c1 + ((c2 + c3) + c4)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(8, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Expression(8, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c0 - c1) +- Branch { true: Expression(7, Sub), false: Counter(4) } at (prev + 0, 18) to (start + 0, 19) + true = ((c0 - c1) - c4) + false = c4 +- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 24) + = ((c0 - c1) - c4) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 23) to (start + 0, 24) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = (c1 + ((c2 + c3) + c4)) + +Function name: mcdc_non_control_flow::assign_3_bis +Raw bytes (82): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 02, 00, 00, 00, 12, 00, 13, 13, 00, 17, 00, 18, 20, 0d, 11, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 7 +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(4) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(1), rhs = Counter(2) +- expression 4 operands: lhs = Expression(5, Sub), rhs = Expression(6, Sub) +- expression 5 operands: lhs = Counter(1), rhs = Counter(2) +- expression 6 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 44) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = ((c2 + c3) + c4) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) +- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Counter(2), false: Expression(5, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = (c1 - c2) +- Code(Expression(4, Add)) at (prev + 0, 23) to (start + 0, 24) + = ((c1 - c2) + (c0 - c1)) +- Branch { true: Counter(3), false: Counter(4) } at (prev + 0, 23) to (start + 0, 24) + true = c3 + false = c4 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = ((c2 + c3) + c4) + +Function name: mcdc_non_control_flow::assign_and +Raw bytes (51): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 07, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(3, Sub) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 33) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = ((c2 + c3) + (c0 - c1)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = ((c2 + c3) + (c0 - c1)) + +Function name: mcdc_non_control_flow::assign_or +Raw bytes (51): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 07, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 32) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = ((c1 + c2) + c3) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Expression(3, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c0 - c1) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = ((c1 + c2) + c3) + +Function name: mcdc_non_control_flow::foo +Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2) + +Function name: mcdc_non_control_flow::func_call +Raw bytes (39): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 05, 01, 29, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 0d, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 3 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 9) to (start + 0, 10) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 14) to (start + 0, 15) + true = c2 + false = c3 +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = ((c2 + c3) + (c0 - c1)) + +Function name: mcdc_non_control_flow::right_comb_tree +Raw bytes (117): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0d, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 1a, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 20, 4a, 19, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 20, 46, 15, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 20, 42, 11, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 20, 09, 0d, 00, 24, 00, 27, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 19 +- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(6, Sub) +- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(6) +- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(5) +- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(4) +- expression 4 operands: lhs = Counter(2), rhs = Counter(3) +- expression 5 operands: lhs = Counter(0), rhs = Counter(1) +- expression 6 operands: lhs = Counter(0), rhs = Counter(1) +- expression 7 operands: lhs = Counter(1), rhs = Counter(6) +- expression 8 operands: lhs = Counter(1), rhs = Counter(6) +- expression 9 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 10 operands: lhs = Counter(1), rhs = Counter(6) +- expression 11 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 12 operands: lhs = Counter(1), rhs = Counter(6) +- expression 13 operands: lhs = Expression(17, Sub), rhs = Counter(4) +- expression 14 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 15 operands: lhs = Counter(1), rhs = Counter(6) +- expression 16 operands: lhs = Expression(17, Sub), rhs = Counter(4) +- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 18 operands: lhs = Counter(1), rhs = Counter(6) +Number of file 0 mappings: 13 +- Code(Counter(0)) at (prev + 32, 1) to (start + 0, 65) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(6, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 19) to (start + 0, 20) +- Branch { true: Expression(18, Sub), false: Counter(6) } at (prev + 0, 19) to (start + 0, 20) + true = (c1 - c6) + false = c6 +- Code(Expression(18, Sub)) at (prev + 0, 25) to (start + 0, 26) + = (c1 - c6) +- Branch { true: Expression(17, Sub), false: Counter(5) } at (prev + 0, 25) to (start + 0, 26) + true = ((c1 - c6) - c5) + false = c5 +- Code(Expression(17, Sub)) at (prev + 0, 31) to (start + 0, 32) + = ((c1 - c6) - c5) +- Branch { true: Expression(16, Sub), false: Counter(4) } at (prev + 0, 31) to (start + 0, 32) + true = (((c1 - c6) - c5) - c4) + false = c4 +- Code(Expression(16, Sub)) at (prev + 0, 36) to (start + 0, 39) + = (((c1 - c6) - c5) - c4) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 36) to (start + 0, 39) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) + diff --git a/tests/coverage/mcdc_non_control_flow.coverage b/tests/coverage/mcdc_non_control_flow.coverage new file mode 100644 index 0000000000000..4e53a7a0d8e85 --- /dev/null +++ b/tests/coverage/mcdc_non_control_flow.coverage @@ -0,0 +1,98 @@ + 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| |// This test ensures that boolean expressions that are not inside control flow + LL| |// decisions are correctly instrumented. + LL| | + LL| |use core::hint::black_box; + LL| | + LL| 3|fn assign_and(a: bool, b: bool) { + LL| 3| let x = a && b; + ^2 + LL| 3| black_box(x); + LL| 3|} + LL| | + LL| 3|fn assign_or(a: bool, b: bool) { + LL| 3| let x = a || b; + ^1 + LL| 3| black_box(x); + LL| 3|} + LL| | + LL| 4|fn assign_3(a: bool, b: bool, c: bool) { + LL| 4| let x = a || b && c; + ^2 ^1 + LL| 4| black_box(x); + LL| 4|} + LL| | + LL| 4|fn assign_3_bis(a: bool, b: bool, c: bool) { + LL| 4| let x = a && b || c; + ^2 ^3 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:19) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | + | 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| 4| black_box(x); + LL| 4|} + LL| | + LL| 3|fn right_comb_tree(a: bool, b: bool, c: bool, d: bool, e: bool) { + LL| 3| let x = a && (b && (c && (d && (e)))); + ^2 ^1 ^1 ^1 + LL| 3| black_box(x); + LL| 3|} + LL| | + LL| 3|fn foo(a: bool) -> bool { + LL| 3| black_box(a) + LL| 3|} + LL| | + LL| 3|fn func_call(a: bool, b: bool) { + LL| 3| foo(a && b); + ^2 + LL| 3|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | assign_and(true, false); + LL| | assign_and(true, true); + LL| | assign_and(false, false); + LL| | + LL| | assign_or(true, false); + LL| | assign_or(true, true); + LL| | assign_or(false, false); + LL| | + LL| | assign_3(true, false, false); + LL| | assign_3(true, true, false); + LL| | assign_3(false, false, true); + LL| | assign_3(false, true, true); + LL| | + LL| | assign_3_bis(true, false, false); + LL| | assign_3_bis(true, true, false); + LL| | assign_3_bis(false, false, true); + LL| | assign_3_bis(false, true, true); + LL| | + LL| | right_comb_tree(false, false, false, true, true); + LL| | right_comb_tree(true, false, false, true, true); + LL| | right_comb_tree(true, true, true, true, true); + LL| | + LL| | func_call(true, false); + LL| | func_call(true, true); + LL| | func_call(false, false); + LL| |} + diff --git a/tests/coverage/mcdc_non_control_flow.rs b/tests/coverage/mcdc_non_control_flow.rs new file mode 100644 index 0000000000000..85c0a6c6ae58a --- /dev/null +++ b/tests/coverage/mcdc_non_control_flow.rs @@ -0,0 +1,72 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 +//@ min-llvm-version: 18 +//@ compile-flags: -Zcoverage-options=mcdc +//@ llvm-cov-flags: --show-mcdc + +// This test ensures that boolean expressions that are not inside control flow +// decisions are correctly instrumented. + +use core::hint::black_box; + +fn assign_and(a: bool, b: bool) { + let x = a && b; + black_box(x); +} + +fn assign_or(a: bool, b: bool) { + let x = a || b; + black_box(x); +} + +fn assign_3(a: bool, b: bool, c: bool) { + let x = a || b && c; + black_box(x); +} + +fn assign_3_bis(a: bool, b: bool, c: bool) { + let x = a && b || c; + black_box(x); +} + +fn right_comb_tree(a: bool, b: bool, c: bool, d: bool, e: bool) { + let x = a && (b && (c && (d && (e)))); + black_box(x); +} + +fn foo(a: bool) -> bool { + black_box(a) +} + +fn func_call(a: bool, b: bool) { + foo(a && b); +} + +#[coverage(off)] +fn main() { + assign_and(true, false); + assign_and(true, true); + assign_and(false, false); + + assign_or(true, false); + assign_or(true, true); + assign_or(false, false); + + assign_3(true, false, false); + assign_3(true, true, false); + assign_3(false, false, true); + assign_3(false, true, true); + + assign_3_bis(true, false, false); + assign_3_bis(true, true, false); + assign_3_bis(false, false, true); + assign_3_bis(false, true, true); + + right_comb_tree(false, false, false, true, true); + right_comb_tree(true, false, false, true, true); + right_comb_tree(true, true, true, true, true); + + func_call(true, false); + func_call(true, true); + func_call(false, false); +} From 6c7c824767e2e9c992da74e449da27889bbd4bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 3 May 2024 09:56:13 +0000 Subject: [PATCH 2/3] coverage: Make MCDC take in account last RHS of condition-coverage Condition coverage extends branch coverage to treat the specific case of last operands of boolean decisions not involved in control flow. This is ultimately made for MCDC to be exhaustive on all boolean expressions. This patch adds a call to `visit_branch_coverage_operation` to track the top-level operand of the said decisions, and changes `visit_coverage_standalone_condition` so MCDC branch registration is called when enabled on these _last RHS_ cases. --- .../rustc_mir_build/src/build/coverageinfo.rs | 68 ++++++++++++------- .../rustc_mir_build/src/build/expr/into.rs | 3 + 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs index 855dcbbcb346e..876faca5172ac 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs @@ -118,17 +118,35 @@ impl BranchInfoBuilder { } } - fn add_two_way_branch<'tcx>( + fn register_two_way_branch<'tcx>( &mut self, + tcx: TyCtxt<'tcx>, cfg: &mut CFG<'tcx>, source_info: SourceInfo, true_block: BasicBlock, false_block: BasicBlock, ) { - let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block); - let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block); - - self.branch_spans.push(BranchSpan { span: source_info.span, true_marker, false_marker }); + // Separate path for handling branches when MC/DC is enabled. + if let Some(mcdc_info) = self.mcdc_info.as_mut() { + let inject_block_marker = + |source_info, block| self.markers.inject_block_marker(cfg, source_info, block); + mcdc_info.visit_evaluated_condition( + tcx, + source_info, + true_block, + false_block, + inject_block_marker, + ); + } else { + let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block); + let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block); + + self.branch_spans.push(BranchSpan { + span: source_info.span, + true_marker, + false_marker, + }); + } } pub(crate) fn into_done(self) -> Option> { @@ -205,7 +223,14 @@ impl<'tcx> Builder<'_, 'tcx> { mir::TerminatorKind::if_(mir::Operand::Copy(place), true_block, false_block), ); - branch_info.add_two_way_branch(&mut self.cfg, source_info, true_block, false_block); + // Separate path for handling branches when MC/DC is enabled. + branch_info.register_two_way_branch( + self.tcx, + &mut self.cfg, + source_info, + true_block, + false_block, + ); let join_block = self.cfg.start_new_block(); self.cfg.goto(true_block, source_info, join_block); @@ -236,22 +261,13 @@ impl<'tcx> Builder<'_, 'tcx> { let source_info = SourceInfo { span: self.thir[expr_id].span, scope: self.source_scope }; - // Separate path for handling branches when MC/DC is enabled. - if let Some(mcdc_info) = branch_info.mcdc_info.as_mut() { - let inject_block_marker = |source_info, block| { - branch_info.markers.inject_block_marker(&mut self.cfg, source_info, block) - }; - mcdc_info.visit_evaluated_condition( - self.tcx, - source_info, - then_block, - else_block, - inject_block_marker, - ); - return; - } - - branch_info.add_two_way_branch(&mut self.cfg, source_info, then_block, else_block); + branch_info.register_two_way_branch( + self.tcx, + &mut self.cfg, + source_info, + then_block, + else_block, + ); } /// If branch coverage is enabled, inject marker statements into `true_block` @@ -270,6 +286,12 @@ impl<'tcx> Builder<'_, 'tcx> { // FIXME(#124144) This may need special handling when MC/DC is enabled. let source_info = SourceInfo { span: pattern.span, scope: self.source_scope }; - branch_info.add_two_way_branch(&mut self.cfg, source_info, true_block, false_block); + branch_info.register_two_way_branch( + self.tcx, + &mut self.cfg, + source_info, + true_block, + false_block, + ); } } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index c08a3b6691afc..6b4dd8b64a425 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -150,6 +150,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::LogicalOp { op, lhs, rhs } => { let condition_scope = this.local_scope(); let source_info = this.source_info(expr.span); + + this.visit_coverage_branch_operation(op, expr.span); + // We first evaluate the left-hand side of the predicate ... let (then_block, else_block) = this.in_if_then_scope(condition_scope, expr.span, |this| { From e15adef457b25b91906fde1510405fa4f3992188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 3 May 2024 10:37:02 +0000 Subject: [PATCH 3/3] tests(coverage): Bless mcdc_non_control_flow tests --- tests/coverage/mcdc_non_control_flow.cov-map | 63 ++++----- tests/coverage/mcdc_non_control_flow.coverage | 122 ++++++++++++++++-- 2 files changed, 147 insertions(+), 38 deletions(-) diff --git a/tests/coverage/mcdc_non_control_flow.cov-map b/tests/coverage/mcdc_non_control_flow.cov-map index 3f422d85e7992..937c36e1f16c4 100644 --- a/tests/coverage/mcdc_non_control_flow.cov-map +++ b/tests/coverage/mcdc_non_control_flow.cov-map @@ -1,5 +1,5 @@ Function name: mcdc_non_control_flow::assign_3 -Raw bytes (73): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 09, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 22, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 20, 1e, 11, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 20, 09, 0d, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 9 @@ -12,29 +12,30 @@ Number of expressions: 9 - expression 6 operands: lhs = Counter(0), rhs = Counter(1) - expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(4) - expression 8 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 9 +Number of file 0 mappings: 10 - Code(Counter(0)) at (prev + 22, 1) to (start + 0, 40) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = (c1 + ((c2 + c3) + c4)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Counter(1), false: Expression(8, Sub) } at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) +- MCDCBranch { true: Counter(1), false: Expression(8, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Expression(8, Sub)) at (prev + 0, 18) to (start + 0, 19) = (c0 - c1) -- Branch { true: Expression(7, Sub), false: Counter(4) } at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Expression(7, Sub), false: Counter(4), condition_id: 2, true_next_id: 3, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) true = ((c0 - c1) - c4) false = c4 - Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 24) = ((c0 - c1) - c4) -- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 23) to (start + 0, 24) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 3, true_next_id: 0, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) true = c2 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = (c1 + ((c2 + c3) + c4)) Function name: mcdc_non_control_flow::assign_3_bis -Raw bytes (82): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 02, 00, 00, 00, 12, 00, 13, 13, 00, 17, 00, 18, 20, 0d, 11, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -50,24 +51,24 @@ Number of file 0 mappings: 10 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c2 + c3) + c4) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) -- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) +- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 3, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) -- MCDCBranch { true: Counter(2), false: Expression(5, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Counter(2), false: Expression(5, Sub), condition_id: 3, true_next_id: 0, false_next_id: 2 } at (prev + 0, 18) to (start + 0, 19) true = c2 false = (c1 - c2) - Code(Expression(4, Add)) at (prev + 0, 23) to (start + 0, 24) = ((c1 - c2) + (c0 - c1)) -- Branch { true: Counter(3), false: Counter(4) } at (prev + 0, 23) to (start + 0, 24) +- MCDCBranch { true: Counter(3), false: Counter(4), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) true = c3 false = c4 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + c4) Function name: mcdc_non_control_flow::assign_and -Raw bytes (51): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 07, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -75,23 +76,24 @@ Number of expressions: 4 - expression 1 operands: lhs = Counter(2), rhs = Counter(3) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) - expression 3 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 7 +Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 12, 1) to (start + 0, 33) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c2 + c3) + (c0 - c1)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) +- MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) -- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) true = c2 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + (c0 - c1)) Function name: mcdc_non_control_flow::assign_or -Raw bytes (51): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 07, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -99,17 +101,18 @@ Number of expressions: 4 - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) - expression 3 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 7 +Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 17, 1) to (start + 0, 32) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c1 + c2) + c3) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) +- MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Expression(3, Sub)) at (prev + 0, 18) to (start + 0, 19) = (c0 - c1) -- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) true = c2 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) @@ -124,27 +127,28 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2) Function name: mcdc_non_control_flow::func_call -Raw bytes (39): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 05, 01, 29, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 0d, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] +Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 00, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub) - expression 2 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 5 +Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10) -- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 9) to (start + 0, 10) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15) +- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15) -- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 14) to (start + 0, 15) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 14) to (start + 0, 15) true = c2 false = c3 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = ((c2 + c3) + (c0 - c1)) Function name: mcdc_non_control_flow::right_comb_tree -Raw bytes (117): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0d, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 1a, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 20, 4a, 19, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 20, 46, 15, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 20, 42, 11, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 20, 09, 0d, 00, 24, 00, 27, 03, 01, 05, 01, 02] +Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 19 @@ -167,31 +171,32 @@ Number of expressions: 19 - expression 16 operands: lhs = Expression(17, Sub), rhs = Counter(4) - expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5) - expression 18 operands: lhs = Counter(1), rhs = Counter(6) -Number of file 0 mappings: 13 +Number of file 0 mappings: 14 - Code(Counter(0)) at (prev + 32, 1) to (start + 0, 65) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Counter(1), false: Expression(6, Sub) } at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 5 } at (prev + 0, 13) to (start + 0, 42) +- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 19) to (start + 0, 20) -- Branch { true: Expression(18, Sub), false: Counter(6) } at (prev + 0, 19) to (start + 0, 20) +- MCDCBranch { true: Expression(18, Sub), false: Counter(6), condition_id: 2, true_next_id: 3, false_next_id: 0 } at (prev + 0, 19) to (start + 0, 20) true = (c1 - c6) false = c6 - Code(Expression(18, Sub)) at (prev + 0, 25) to (start + 0, 26) = (c1 - c6) -- Branch { true: Expression(17, Sub), false: Counter(5) } at (prev + 0, 25) to (start + 0, 26) +- MCDCBranch { true: Expression(17, Sub), false: Counter(5), condition_id: 3, true_next_id: 4, false_next_id: 0 } at (prev + 0, 25) to (start + 0, 26) true = ((c1 - c6) - c5) false = c5 - Code(Expression(17, Sub)) at (prev + 0, 31) to (start + 0, 32) = ((c1 - c6) - c5) -- Branch { true: Expression(16, Sub), false: Counter(4) } at (prev + 0, 31) to (start + 0, 32) +- MCDCBranch { true: Expression(16, Sub), false: Counter(4), condition_id: 4, true_next_id: 5, false_next_id: 0 } at (prev + 0, 31) to (start + 0, 32) true = (((c1 - c6) - c5) - c4) false = c4 - Code(Expression(16, Sub)) at (prev + 0, 36) to (start + 0, 39) = (((c1 - c6) - c5) - c4) -- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 36) to (start + 0, 39) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 5, true_next_id: 0, false_next_id: 0 } at (prev + 0, 36) to (start + 0, 39) true = c2 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) diff --git a/tests/coverage/mcdc_non_control_flow.coverage b/tests/coverage/mcdc_non_control_flow.coverage index 4e53a7a0d8e85..cd733885a98b6 100644 --- a/tests/coverage/mcdc_non_control_flow.coverage +++ b/tests/coverage/mcdc_non_control_flow.coverage @@ -12,18 +12,76 @@ LL| 3|fn assign_and(a: bool, b: bool) { LL| 3| let x = a && b; ^2 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:19) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | + | 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| 3| black_box(x); LL| 3|} LL| | LL| 3|fn assign_or(a: bool, b: bool) { LL| 3| let x = a || b; ^1 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:19) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, F = F } + | 2 { T, - = T } + | + | C1-Pair: covered: (1,2) + | C2-Pair: not covered + | MC/DC Coverage for Decision: 50.00% + | + ------------------ LL| 3| black_box(x); LL| 3|} LL| | LL| 4|fn assign_3(a: bool, b: bool, c: bool) { LL| 4| let x = a || b && c; ^2 ^1 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:24) + | + | Number of Conditions: 3 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | Condition C3 --> (LL:23) + | + | Executed MC/DC Test Vectors: + | + | C1, C2, C3 Result + | 1 { F, F, - = F } + | 2 { T, -, - = T } + | 3 { F, T, T = T } + | + | C1-Pair: covered: (1,2) + | C2-Pair: covered: (1,3) + | C3-Pair: not covered + | MC/DC Coverage for Decision: 66.67% + | + ------------------ LL| 4| black_box(x); LL| 4|} LL| | @@ -31,22 +89,24 @@ LL| 4| let x = a && b || c; ^2 ^3 ------------------ - |---> MC/DC Decision Region (LL:13) to (LL:19) + |---> MC/DC Decision Region (LL:13) to (LL:24) | - | Number of Conditions: 2 + | Number of Conditions: 3 | Condition C1 --> (LL:13) | Condition C2 --> (LL:18) + | Condition C3 --> (LL:23) | | Executed MC/DC Test Vectors: | - | C1, C2 Result - | 1 { F, - = F } - | 2 { T, F = F } - | 3 { T, T = T } + | C1, C2, C3 Result + | 1 { T, F, F = F } + | 2 { F, -, T = T } + | 3 { T, T, - = T } | - | C1-Pair: covered: (1,3) - | C2-Pair: covered: (2,3) - | MC/DC Coverage for Decision: 100.00% + | C1-Pair: not covered + | C2-Pair: covered: (1,3) + | C3-Pair: not covered + | MC/DC Coverage for Decision: 33.33% | ------------------ LL| 4| black_box(x); @@ -55,6 +115,31 @@ LL| 3|fn right_comb_tree(a: bool, b: bool, c: bool, d: bool, e: bool) { LL| 3| let x = a && (b && (c && (d && (e)))); ^2 ^1 ^1 ^1 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:42) + | + | Number of Conditions: 5 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:19) + | Condition C3 --> (LL:25) + | Condition C4 --> (LL:31) + | Condition C5 --> (LL:36) + | + | Executed MC/DC Test Vectors: + | + | C1, C2, C3, C4, C5 Result + | 1 { F, -, -, -, - = F } + | 2 { T, F, -, -, - = F } + | 3 { T, T, T, T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | C3-Pair: not covered + | C4-Pair: not covered + | C5-Pair: not covered + | MC/DC Coverage for Decision: 40.00% + | + ------------------ LL| 3| black_box(x); LL| 3|} LL| | @@ -65,6 +150,25 @@ LL| 3|fn func_call(a: bool, b: bool) { LL| 3| foo(a && b); ^2 + ------------------ + |---> MC/DC Decision Region (LL:9) to (LL:15) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:9) + | Condition C2 --> (LL:14) + | + | 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| 3|} LL| | LL| |#[coverage(off)]