Every point of entry and exit in the program has been invoked at least once, every condition in a decision in the program has taken all possible outcomes at least once, every decision in the program has taken all possible outcomes at least once, and each condition in a decision has been shown to independently affect that decision’s outcome.A condition is shown to independently affect a decision’s outcome by: (1) varying just that condition while holding fixed all other possible conditions or (2) varying just that condition while holding fixed all other possible conditions that could affect the outcome.
A | B | A and B |
False | – | False |
– | False | False |
True | True | True |
The minus sign (-) is ambiguous in this table because it traditionally means “don’t care”, but for programming languages which implement the short circuit, it means “don’t evaluate”. This is a big difference as the evaluation of an expression can have side effects. Also, due to the fact that the order of evaluation is from left to right, this table is for C, C++ and C#:
A | B | A and B |
False | Don’t evaluate | False |
True | False | False |
True | True | True |
Let see a practical sample of the new definition’s impact: If we take the expression “X = ( A or B ) and C” we will get the following truth table:
A | B | C | (A or B) and C |
True | Don’t evaluate | False | False |
False | True | False | False |
True | Don’t evaluate | True | True |
False | True | True | True |
False | False | Don’t evaluate | False |
- All other vectors are modifying the other conditions. So A is not allowed to be True and C is not allowed to be False. This is the constraint introduced by the point (1) of the MC/DC definition.
- The point (2) allows that conditions which have no impact to the output can be ignored. This applied to the test vector A=False and B=False.
Without the point (2), it would be necessary to create a test vector which fits A=False, B=False and C=True which is not possible if it is not allowed to evaluate C.
To be more concrete, let’s analyze a small C++ sample which uses a short circuit and shows us why the new clause (2) applies to it:
bool log( const char *text ) { static FILE *f = NULL; if ( ( f || f=fopen("logfile.txt","a+") ) && fputs( text, f ) != EOF ) { fflush( f ); return true; } else return false; }
This code simply opens a log file (if not already opened) and writes text into it.
The truth table of the ‘if‘ statement is:
f | f=fopen(“logfile.txt,”a+”) | fputs(text,f)!=EOF | if statement |
True | Don’t evaluate | False | False |
False | True | False | False |
True | Don’t evaluate | True | True |
False | True | True | True |
False | False | Don’t evaluate | False |
This simple example illustrates why toggling all conditions is not allowed: we use the same test pattern as above: ‘f’=False, ‘f=fopen(“logfile.txt,”a+”)‘=True and ‘fputs(text,f)!=EOF‘=True. Then we decide to only toggle ‘f=fopen(“logfile.txt,”a+”)‘. The test pattern without short cut would be: ‘f’=False, ‘f=fopen(“logfile.txt,”a+”)‘=False and ‘fputs(text,f)!=EOF‘=True. The programmer has used the short circuit facility of C++ to avoid a crash when calling fputs with a NULL pointer. That’s why it is necessary to apply the new clause (2) of the DO-178C and omit the evaluation of ‘fputs(text,f)!=EOF‘.
Learn more about Squish Coco, supporting MC/DC, at https://coco.froglogic.com.
The post Squish Coco: MC/DC Coverage and Short Circuit Explained appeared first on froglogic.