-
Notifications
You must be signed in to change notification settings - Fork 14k
Description
Introduction
Modified condition/decision coverage (MC/DC) is a code coverage criterion used widely in safety critical software components and is required by standards such as DO-178B and ISO26262.
Terminology
condition: boolean expressions that have no binary logical operators. For example, a || b is not "condition" because it has an or operator while a==b is.
decision: longest boolean expressions composed of conditions and binary boolean expressions only.
MC/DC requires each condition in a decision is shown to independently affect the outcome of the decision.
e.g Suppose we have code like
if (a || b) && c {
todo!();
}Here (a || b) && c is a decision and a,b,c are conditions.
- If test cases are
(a=true, b=false, c=true)and(a=false, b=false, c=true), we sayacan independently affect the decision because the value of decision is changed asachanges while keepbandcunchanged. So that we get 1/3 MC/DC here (1 foraand 3 fora,b,c). - Test cases
(a=false, b=true, c=true)and(a=false, b=false, c=false)also showbcan independently affect the decision. Though in the later casecis also changed but it is short-circuited and has no impacts (thus we can view it as same asc=true). Whilecis not acknowledged due to change ofb. Plus the two cases before we get 2/3 MC/DC. - Test cases
(a=true,b=false,c=true)and(a=true,b=false,c=false)showccan do the same. By now we get 3/3.
Notice that there are duplicate cases, so test cases collection {(a=true, b=false, c=true),(a=false, b=false, c=true),(a=false, b=true, c=true), (a=false, b=false, c=false),(a=true,b=false,c=false)} are sufficient to prove 3/3 MC/DC.
In fact we can use at least n+1 cases to prove 100% MC/DC of decision with n conditions. (In this example, {(a=true,b=false,c=true),(a=false,b=false,c=true),(a=false,b=true,c=true),(a=true,b=false,c=false)} are enough)
Progress
A basic implementation for MC/DC is filed on #123409 , which has some limits. There are still several cases need to handle:
- Support plain boolean expressions like
let val = a || b. Done at
coverage: Optionally instrument the RHS of lazy logical operators #125756
MCDC Coverage: instrument last boolean RHS operands from condition coverage #125766 - Support pattern matching. Ferrous suggests that refutable patterns should be considered as decisions, which sounds certainly reasonable as these are considered as branches too.
Draft: Support mcdc analysis for pattern matching #124278 - Support nested decisions like
if (a || b) || inner_decision(c || d). Done at MCDC coverage: support nested decision coverage #124255 - So far only decisions with at most 6 conditions are counted due to resource cost. This limit should be relaxed now that the llvm backend had this optimization.
[Coverage][MCDC] Adapt mcdc to llvm 19 #126733
Known Issues
- Decisions containing constant conditions may result incorrect report, where some non-constant conditions are regarded as constants or vice versa. This issue occurs because the way rustc produces counters for constants is not what llvm expects. It's fixed by llvm #112694 and can be solved once rustc upgraded in-tree llvm to 20.
- Some nested decisions may cause panic as llvm #91600 described.
- On some occasions rustc may painic with "instrprof failed to lower mcdc parameters", see [Coverage][MCDC] Do not initialize mcdc parameters for instances containing no mcdc statements #129989