757 lines
20 KiB
C
757 lines
20 KiB
C
#include "coverage.h"
|
|
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
#define CTRL_IDX 0xa
|
|
#define FUNCTION_LIKE_MACRO(idx__, val__) do { \
|
|
(array[(idx__)] != 0xffu && array[(idx__) + 1u] != 0xffu) ? \
|
|
(((idx__) == (val__)) ? SetFalse(&(val__)) : SetTrue(&(val__))) : \
|
|
SetFalse(&(val__)); \
|
|
} while (0)
|
|
|
|
|
|
struct Compound {
|
|
int a;
|
|
int b;
|
|
int c;
|
|
int d;
|
|
int e;
|
|
int f;
|
|
};
|
|
|
|
enum Color {
|
|
RED = 0,
|
|
YELLOW = -1,
|
|
BLUE = 1,
|
|
ORANGE = -2,
|
|
GREEN = 2,
|
|
};
|
|
|
|
|
|
static volatile unsigned char array[5] = { 0xff, 0xff, 0xa, 0xb, 0 };
|
|
|
|
|
|
static int Identity(int const a)
|
|
{
|
|
return a;
|
|
}
|
|
|
|
|
|
static void SetTrue(int* value)
|
|
{
|
|
value[0] = TRUE;
|
|
}
|
|
|
|
|
|
static void SetFalse(int* value)
|
|
{
|
|
value[0] = FALSE;
|
|
}
|
|
|
|
|
|
static int TestFunctionLikeMacro(void)
|
|
{
|
|
int result = -1;
|
|
FUNCTION_LIKE_MACRO(0, result);
|
|
return result;
|
|
}
|
|
|
|
|
|
static unsigned ComplexBooleanParameter(int const a, int const b, int const c, int const d)
|
|
{
|
|
unsigned outcome = FALSE;
|
|
|
|
if (Identity((!a || !(b > -36)) && (!Identity(c) && !(Identity(d) > 2)))) {
|
|
outcome = TRUE;
|
|
}
|
|
else {
|
|
outcome = FALSE;
|
|
}
|
|
return outcome;
|
|
}
|
|
|
|
|
|
static void TestComplexBooleanParameter(void)
|
|
{
|
|
ComplexBooleanParameter(-4768, 5003, 8031, 5240);
|
|
ComplexBooleanParameter(-4768, -36, 6858, 5240);
|
|
ComplexBooleanParameter(-4768, -36, 0, 3335);
|
|
ComplexBooleanParameter(0, -102, 0, 2);
|
|
ComplexBooleanParameter(-4768, -36, 0, 2);
|
|
}
|
|
|
|
|
|
static unsigned ComplexFor(int const a, int const b, int const c, int const d)
|
|
{
|
|
unsigned num_cycles = 0u;
|
|
|
|
for (; (((a || b) && (c > -23)) || (Identity(d) < 5)); num_cycles++) {
|
|
|
|
if (num_cycles > 1u) {
|
|
break;
|
|
}
|
|
}
|
|
return num_cycles;
|
|
}
|
|
|
|
|
|
static void TestComplexFor(void)
|
|
{
|
|
/* Set of test vectors for MC/DC */
|
|
ComplexFor(0, 0, -22, 5);
|
|
ComplexFor(0, 0, -23, 5);
|
|
ComplexFor(0, 1, -23, 5);
|
|
ComplexFor(0, 0, -23, 4);
|
|
ComplexFor(0, 1, -22, 5);
|
|
ComplexFor(1, 0, -22, 5);
|
|
}
|
|
|
|
|
|
static unsigned ComplexDoWhile(int const a, int const b, int const c, int const d)
|
|
{
|
|
unsigned num_cycles = 0u;
|
|
|
|
do {
|
|
if (num_cycles > 1u) {
|
|
break;
|
|
}
|
|
num_cycles++;
|
|
}
|
|
while (((!(Identity(a) >= -45) && Identity(b)) && Identity(c)) || d);
|
|
|
|
return num_cycles;
|
|
}
|
|
|
|
|
|
static void TestComplexDoWhile(void)
|
|
{
|
|
/* Set of test vectors for MC/DC */
|
|
ComplexDoWhile(-45, 1, 1, 0);
|
|
ComplexDoWhile(-46, 0, 0, 0);
|
|
ComplexDoWhile(-46, 0, 1, 0);
|
|
ComplexDoWhile(-46, 1, 0, 0);
|
|
ComplexDoWhile(-46, 0, 0, 1);
|
|
ComplexDoWhile(-46, 1, 1, 0);
|
|
}
|
|
|
|
|
|
static unsigned ComplexWhile(int const a, int const b, int const c, int const d)
|
|
{
|
|
unsigned num_cycles = 0u;
|
|
|
|
while ((!(a > -70) && !(Identity(b) == 39)) || !(c <= -13) || (Identity(d) < 39)) {
|
|
|
|
if (num_cycles > 1u) {
|
|
break;
|
|
}
|
|
num_cycles++;
|
|
}
|
|
return num_cycles;
|
|
}
|
|
|
|
|
|
static void TestComplexWhile(void)
|
|
{
|
|
/* Set of test vectors for MC/DC */
|
|
ComplexWhile(-69, 40, -13, 39);
|
|
ComplexWhile(-70, 39, -13, 39);
|
|
ComplexWhile(-70, 39, -12, 39);
|
|
ComplexWhile(-70, 39, -13, 38);
|
|
ComplexWhile(-70, 40, -13, 39);
|
|
}
|
|
|
|
|
|
static unsigned ComplexIf(int const a, int const b, int const c, int const d)
|
|
{
|
|
unsigned outcome = FALSE;
|
|
|
|
if (a && !(b > -100 || !(c > 42)) && Identity(d) < 36) {
|
|
outcome = TRUE;
|
|
}
|
|
else {
|
|
outcome = FALSE;
|
|
}
|
|
return outcome;
|
|
}
|
|
|
|
|
|
static void TestComplexIf(void)
|
|
{
|
|
/* Set of test vectors for MC/DC */
|
|
ComplexIf(0, -100, 42, 36);
|
|
ComplexIf(1, -99, 42, 36);
|
|
ComplexIf(1, -100, 42, 36);
|
|
ComplexIf(1, -100, 43, 36);
|
|
ComplexIf(1, -100, 43, 35);
|
|
}
|
|
|
|
|
|
static int SwitchCase(enum Color const color)
|
|
{
|
|
int offset = 0;
|
|
|
|
switch (color) {
|
|
case RED:
|
|
offset = 10;
|
|
break;
|
|
case BLUE:
|
|
offset = 8;
|
|
break;
|
|
case ORANGE:
|
|
offset = 6;
|
|
break;
|
|
case YELLOW:
|
|
case GREEN:
|
|
offset = 2;
|
|
break;
|
|
default:
|
|
offset = -1;
|
|
break;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
|
|
static void TestSwitchCase(int const tic)
|
|
{
|
|
/* Switch-case expression
|
|
*
|
|
* There are several options for compilers to model switch-case
|
|
* expressions. Representations containing jump or value tables are not
|
|
* suitable for a trace-based measurement of code coverage. It is possible
|
|
* for most compilers to suppress the creation of jump tables via compiler
|
|
* flags. The result is a binary search incorporating conditional branches
|
|
* that suitable for monitoring the status of each condition.
|
|
*/
|
|
|
|
if (tic) {
|
|
/* Set of test vectors for MC/DC */
|
|
SwitchCase(RED);
|
|
SwitchCase(BLUE);
|
|
SwitchCase(ORANGE);
|
|
SwitchCase(YELLOW);
|
|
SwitchCase(GREEN);
|
|
|
|
SwitchCase(3); /* Lower than expected input range */
|
|
SwitchCase(-3); /* Higher than expected input range */
|
|
}
|
|
else {
|
|
/* Expected input range */
|
|
SwitchCase(RED);
|
|
SwitchCase(BLUE);
|
|
SwitchCase(ORANGE);
|
|
SwitchCase(YELLOW);
|
|
SwitchCase(GREEN);
|
|
}
|
|
}
|
|
|
|
|
|
static unsigned MultiLine(struct Compound *compound)
|
|
{
|
|
if ( ( compound->a == TRUE
|
|
|| compound->b == TRUE
|
|
|| compound->c == TRUE)
|
|
&& ( compound->d == TRUE
|
|
|| compound->e == TRUE
|
|
|| compound->f == TRUE)) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static void TestMultiline(void)
|
|
{
|
|
/* Multi-line multi-operator decision
|
|
*
|
|
* Each operator resides on a distinct line, so compilers may choose
|
|
* to create additional entries in the debug symbol information per
|
|
* line. However, even though this may improve debugging it also
|
|
* conceals the direct relationship of these lines. A semantic analysis
|
|
* is required to restore this relationship and reason about the decision
|
|
* as a whole.
|
|
*/
|
|
|
|
/* Set of test vectors for decision coverage */
|
|
struct Compound compound = {0};
|
|
|
|
compound.a = FALSE;
|
|
compound.b = FALSE;
|
|
compound.c = FALSE;
|
|
compound.d = TRUE;
|
|
compound.e = TRUE;
|
|
compound.f = TRUE;
|
|
if (MultiLine(&compound) == TRUE) {
|
|
return;
|
|
}
|
|
|
|
compound.b = TRUE;
|
|
MultiLine(&compound);
|
|
}
|
|
|
|
|
|
static unsigned NestedExprTrans(int a, int b, float c)
|
|
{
|
|
/* Equivalence transformation for decision with nested Boolean expression
|
|
*
|
|
* Equivalent expression after transformation. The nested Boolean
|
|
* expression is extracted and put into a branching context. Compilers
|
|
* typically choose to use conditional branches for modelling this type of
|
|
* structure.
|
|
*/
|
|
int tmp = 0;
|
|
|
|
if ((float) b < c) {
|
|
tmp = 1;
|
|
}
|
|
|
|
if (a > (b + tmp)) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static unsigned NestedExpr(int a, int b, float c)
|
|
{
|
|
/* Decision with nested Boolean expression
|
|
*
|
|
* Expression showing a nested Boolean expression. Compilers may choose to
|
|
* model nested expressions with conditional or unconditional instructions
|
|
* instead of conditional branches that are not suitable for the trace-
|
|
* based measurement of code coverage.
|
|
*/
|
|
return (a > (b + ((float) b < c)));
|
|
}
|
|
|
|
|
|
static void TestExprNesting(void)
|
|
{
|
|
/* Decision with nested Boolean expression
|
|
*
|
|
* The decision contains a nested Boolean expression. Both decision and
|
|
* nested expression must be analyzed as two distinct decisions. Compilers
|
|
* may choose to model nested expressions with conditional or unconditional
|
|
* instructions instead of conditional branches that are not suitable for
|
|
* the trace-based measurement of code coverage. Transforming the
|
|
* expression into a branching context may force the use of conditional
|
|
* instructions.
|
|
*/
|
|
|
|
/* Set of test vectors for MC/DC */
|
|
NestedExpr(1, 1, 3.0f); /* top: T, nested: T */
|
|
NestedExpr(6, 4, 3.0f); /* top: F, nested: F */
|
|
|
|
/* Transformed expression */
|
|
NestedExprTrans(1, 1, 3.0f); /* top: T, nested: T */
|
|
NestedExprTrans(6, 4, 3.0f); /* top: F, nested: F */
|
|
}
|
|
|
|
|
|
static float TernaryExprTrans(float const a, float const b)
|
|
{
|
|
/* Equivalence transformation for ternary expression
|
|
*
|
|
* Equivalent expression after transformation. The decision appears in a
|
|
* branching context once more. Compilers typically choose to use
|
|
* conditional branches for modelling this type of expression.
|
|
*/
|
|
if (a >= b) {
|
|
return a;
|
|
}
|
|
else {
|
|
return b;
|
|
}
|
|
}
|
|
|
|
|
|
static float TernaryExpr(float const a, float const b)
|
|
{
|
|
/* Ternary expression as decision
|
|
*
|
|
* Expression showing a decision with ternary expression. Compilers may
|
|
* choose to model ternanry expressions with conditional or unconditional
|
|
* instructions instead of conditional branches that are not suitable for
|
|
* the trace-based measurement of code coverage.
|
|
*/
|
|
return (a >= b) ? a : b;
|
|
}
|
|
|
|
|
|
static void TestTernaryExpr(void)
|
|
{
|
|
/* Test for ternary expression as decision
|
|
*
|
|
* Compilers may choose to model ternanry expressions with conditional or
|
|
* unconditional instructions instead of conditional branches that are not
|
|
* suitable for the trace-based measurement of code coverage. Transforming
|
|
* the expression into a branching context may force the use of conditional
|
|
* instructions.
|
|
*/
|
|
|
|
/* Set of test vectors for both MC/DC and OBC */
|
|
TernaryExpr(0.0f, 0.0f);
|
|
TernaryExpr(0.0f, 1.0f);
|
|
|
|
/* Transformed expression */
|
|
TernaryExprTrans(0.0f, 0.0f);
|
|
TernaryExprTrans(0.0f, 1.0f);
|
|
}
|
|
|
|
|
|
static int SimpleIfFunctionCall(int const a)
|
|
{
|
|
/* If-then block controlled by nested function call
|
|
*
|
|
* The expression shows an expression in branching context. The outcome of
|
|
* the decision is controlled by the Boolean return value of a simple
|
|
* function.
|
|
*/
|
|
if (Identity(a)) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void TestSimpleIfFunctionCall(void)
|
|
{
|
|
/* Test for if-then construct with nested function call
|
|
*
|
|
* Tests whether the compiler uses conditional branches to model this
|
|
* simple expression type.
|
|
*/
|
|
SimpleIfFunctionCall(0);
|
|
SimpleIfFunctionCall(1);
|
|
}
|
|
|
|
|
|
static int BooleanAssignmentRelExprTrans(int const a, int const b)
|
|
{
|
|
/* Equivalence transformation for relational expression
|
|
*
|
|
* Equivalent expression after transformation. The decision appears in a
|
|
* branching context once more. Compilers typically choose to use
|
|
* conditional branches for modelling this type of expression.
|
|
*/
|
|
if (a == b) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static int BooleanAssignmentRelExpr(int const a, int const b)
|
|
{
|
|
/* Relational expression as decision
|
|
*
|
|
* Expression showing a decision in non-branching context. Compilers may
|
|
* choose to model Boolean assignments with conditional or unconditional
|
|
* instructions instead of conditional branches that are not suitable for
|
|
* the trace-based measurement of code coverage.
|
|
*/
|
|
return a == b;
|
|
}
|
|
|
|
|
|
static void TestNoBranchCtxRelExpr(void)
|
|
{
|
|
/* Test for relational expression as decision
|
|
*
|
|
* Relational operators are no Boolean operators. Hence, the decision
|
|
* has a single condition.
|
|
* Compilers may choose to model Boolean assignments with conditional or
|
|
* unconditional instructions instead of conditional branches that are not
|
|
* suitable for the trace-based measurement of code coverage. Transforming
|
|
* the expression into a branching context may force the use of conditional
|
|
* instructions.
|
|
*/
|
|
|
|
/* Set of test vectors for both MC/DC and OBC */
|
|
BooleanAssignmentRelExpr(0, 0);
|
|
BooleanAssignmentRelExpr(0, 1);
|
|
|
|
/* Transformed expression */
|
|
BooleanAssignmentRelExprTrans(0, 0);
|
|
BooleanAssignmentRelExprTrans(0, 1);
|
|
}
|
|
|
|
|
|
static int BooleanAssignmentNotOp(int const a, int const b, int const c)
|
|
{
|
|
/* Decision in assignment
|
|
*
|
|
* Boolan expression that does not occur in branching context.
|
|
*
|
|
* Structure: Truth table: Test vectors for MC/DC:
|
|
*
|
|
* a----> F a b c | outcome a: 1. + 2.
|
|
* \ -------+--------- b: 2. + 3.
|
|
* b----> F 1. F x x | F c: 2. + 4.
|
|
* |\ 2. T F F | T
|
|
* | c----> F 3. T T x | F
|
|
* v | 4. T F T | F
|
|
* T v
|
|
* T
|
|
*/
|
|
return a && !(b || c);
|
|
}
|
|
|
|
|
|
static void TestNoBranchCtxNotOp(void)
|
|
{
|
|
/* Test for decision in assignment
|
|
*
|
|
* Boolan expression that does not occur in branching context.
|
|
*
|
|
* Decision: a && !(b || c)
|
|
*
|
|
* Structure: Truth table: Test vectors for MC/DC:
|
|
*
|
|
* a----> F a b c | outcome a: 1. + 2.
|
|
* \ -------+--------- b: 2. + 3.
|
|
* b----> F 1. F x x | F c: 2. + 4.
|
|
* |\ 2. T F F | T
|
|
* | c----> F 3. T T x | F
|
|
* v | 4. T F T | F
|
|
* T v
|
|
* T
|
|
*/
|
|
|
|
/* Set of test vectors for both MC/DC and OBC */
|
|
BooleanAssignmentNotOp(0, 1, 1); /* 1. */
|
|
BooleanAssignmentNotOp(1, 0, 0); /* 2. */
|
|
BooleanAssignmentNotOp(1, 1, 1); /* 3. */
|
|
BooleanAssignmentNotOp(1, 0, 1); /* 4. */
|
|
}
|
|
|
|
|
|
static int BooleanExprCoupledTerms(int const a, int const b)
|
|
{
|
|
/* Decision with strongly coupled terms
|
|
*
|
|
* Each condition that appears more than once is treated like
|
|
* a distinct condition. Masking of subexpressions is used to find
|
|
* independence pairs that are suitable even though more than one value
|
|
* is changing at the same time.
|
|
*
|
|
* Structure: Truth table: Test vectors for MC/DC:
|
|
*
|
|
* a---+ a b | outcome a(1): 1. + 2.
|
|
* \ | -----+--------- b(1): 2. + 4.
|
|
* b-+--> F 1. F F | F a(2): 3. + 4.
|
|
* |\v 2. T F | T b(2): 1. + 3.
|
|
* | a----> F 3. F T | T
|
|
* | \ 4. T T | F
|
|
* v b----> F
|
|
* T |
|
|
* v
|
|
* T
|
|
*/
|
|
unsigned outcome = FALSE;
|
|
|
|
if ((a && !b) || (!a && b)) {
|
|
outcome = TRUE;
|
|
}
|
|
else {
|
|
outcome = FALSE;
|
|
}
|
|
return outcome;
|
|
}
|
|
|
|
|
|
static void TestMaskingMcdc(void)
|
|
{
|
|
/* Test for decision with strongly coupled terms
|
|
*
|
|
* Each condition that appears more than once is treated like
|
|
* a distinct condition. Masking of subexpressions is used to find
|
|
* independence pairs that are suitable even though more than one value
|
|
* is changing at the same time.
|
|
*
|
|
* Decision: (a && !b) || (!a && b)
|
|
*
|
|
* Structure: Truth table: Test vectors for MC/DC:
|
|
*
|
|
* a---+ a b | outcome a(1): 1. + 2.
|
|
* \ | -----+--------- b(1): 2. + 4.
|
|
* b-+--> F 1. F F | F a(2): 3. + 4.
|
|
* |\v 2. T F | T b(2): 1. + 3.
|
|
* | a----> F 3. F T | T
|
|
* | \ 4. T T | F
|
|
* v b----> F
|
|
* T |
|
|
* v
|
|
* T
|
|
*/
|
|
|
|
/* Set of test vectors for MC/DC */
|
|
BooleanExprCoupledTerms(0, 0); /* 1. */
|
|
BooleanExprCoupledTerms(1, 0); /* 2. */
|
|
BooleanExprCoupledTerms(0, 1); /* 3. */
|
|
BooleanExprCoupledTerms(1, 1); /* 4. */
|
|
}
|
|
|
|
|
|
static unsigned BooleanExprMixedOps(int const a, int const b, int const c)
|
|
{
|
|
/* Deviation of MC/DC and OBC
|
|
*
|
|
* The structure of the decision results in the deviation of MC/DC and
|
|
* Object Code Branch Coverage. Full coverage of all conditional branches
|
|
* at the object code level alone is not sufficient to achieve MC/DC.
|
|
*
|
|
* Structure: Truth table: Test vectors for MC/DC:
|
|
*
|
|
* a----+ a b c | outcome a: 1. + 5.
|
|
* | | -------+--------- b: 3. + 5.
|
|
* v | 1. T x T | T c: 1. + 2.
|
|
* b | 2. T x F | F
|
|
* |\ v 3. F T T | T Test vectors for OBC:
|
|
* | +->c---->T 4. F T F | F 2. + 3. + 5.
|
|
* | | 5. F F x | F
|
|
* v v
|
|
* F F
|
|
*/
|
|
unsigned outcome = FALSE;
|
|
|
|
if ((a || b) && c) {
|
|
outcome = TRUE;
|
|
}
|
|
else {
|
|
outcome = FALSE;
|
|
}
|
|
return outcome;
|
|
}
|
|
|
|
|
|
static void TestObcDiffersMcdc(int const tic)
|
|
{
|
|
/* Test for deviation of MC/DC and OBC
|
|
*
|
|
* The structure of the decision results in the deviation of MC/DC and
|
|
* Object Code Branch Coverage. Full coverage of all conditional branches
|
|
* at the object code level alone is not sufficient to achieve MC/DC.
|
|
*
|
|
* Decision: (a || b) && c
|
|
*
|
|
* Structure: Truth table: Test vectors for MC/DC:
|
|
*
|
|
* a----+ a b c | outcome a: 1. + 5.
|
|
* | | -------+--------- b: 3. + 5.
|
|
* v | 1. T x T | T c: 1. + 2.
|
|
* b | 2. T x F | F
|
|
* |\ v 3. F T T | T Test vectors for OBC:
|
|
* | +->c---->T 4. F T F | F 2. + 3. + 5.
|
|
* | | 5. F F x | F
|
|
* v v
|
|
* F F
|
|
*/
|
|
if (tic) {
|
|
/* Set of test vectors for MC/DC */
|
|
BooleanExprMixedOps(1, 0, 1); /* 1. */
|
|
BooleanExprMixedOps(1, 0, 0); /* 2. */
|
|
BooleanExprMixedOps(0, 1, 1); /* 3. */
|
|
BooleanExprMixedOps(0, 0, 0); /* 5. */
|
|
}
|
|
else {
|
|
/* Set of test vectors for OBC */
|
|
BooleanExprMixedOps(1, 0, 0); /* 2. */
|
|
BooleanExprMixedOps(0, 1, 1); /* 3. */
|
|
BooleanExprMixedOps(0, 0, 0); /* 5. */
|
|
}
|
|
}
|
|
|
|
|
|
static unsigned BooleanExprSameOps(int const a, int const b, int const c)
|
|
{
|
|
/* Equivalence of MC/DC and OBC
|
|
*
|
|
* The structure of the decision results in the equivalence of MC/DC
|
|
* and Object Code Branch Coverage. Full coverage of all conditional
|
|
* branches at the object code level is sufficient to achieve MC/DC.
|
|
*
|
|
* Structure: Truth table: Test vectors for MC/DC:
|
|
*
|
|
* a----> T a b c | outcome a: 1. + 4.
|
|
* \ -------+--------- b: 2. + 4.
|
|
* b----> T 1. T x x | T c: 3. + 4.
|
|
* \ 2. F T x | T
|
|
* c----> T 3. F F T | T
|
|
* | 4. F F F | F
|
|
* v
|
|
* F
|
|
*/
|
|
unsigned outcome = FALSE;
|
|
|
|
if (a || b || c) {
|
|
outcome = TRUE;
|
|
}
|
|
else {
|
|
outcome = FALSE;
|
|
}
|
|
return outcome;
|
|
}
|
|
|
|
|
|
static void TestObcEqualsMcdc(void)
|
|
{
|
|
/* Test for equivalence of MC/DC and OBC
|
|
*
|
|
* The structure of the decision results in the equivalence of MC/DC
|
|
* and Object Code Branch Coverage. Full coverage of all conditional
|
|
* branches at the object code level is sufficient to achieve MC/DC.
|
|
*
|
|
* Decision: a || b || c
|
|
*
|
|
* Structure: Truth table: Test vectors for MC/DC:
|
|
*
|
|
* a----> T a b c | outcome a: 1. + 4.
|
|
* \ -------+--------- b: 2. + 4.
|
|
* b----> T 1. T x x | T c: 3. + 4.
|
|
* \ 2. F T x | T
|
|
* c----> T 3. F F T | T
|
|
* | 4. F F F | F
|
|
* v
|
|
* F
|
|
*/
|
|
|
|
/* Set of test vectors for both MC/DC and OBC */
|
|
BooleanExprSameOps(1, 0, 0); /* 1. */
|
|
BooleanExprSameOps(0, 1, 0); /* 2. */
|
|
BooleanExprSameOps(0, 0, 1); /* 3. */
|
|
BooleanExprSameOps(0, 0, 0); /* 4. */
|
|
}
|
|
|
|
|
|
void RunCoverageDemo(void)
|
|
{
|
|
static unsigned tic = 1u;
|
|
|
|
while (TRUE) {
|
|
tic = !tic;
|
|
|
|
TestObcEqualsMcdc();
|
|
TestObcDiffersMcdc(tic);
|
|
TestMaskingMcdc();
|
|
|
|
TestNoBranchCtxNotOp();
|
|
TestNoBranchCtxRelExpr();
|
|
TestSimpleIfFunctionCall();
|
|
TestTernaryExpr();
|
|
TestExprNesting();
|
|
TestMultiline();
|
|
TestSwitchCase(tic);
|
|
|
|
TestComplexIf();
|
|
TestComplexFor();
|
|
TestComplexWhile();
|
|
TestComplexDoWhile();
|
|
TestComplexBooleanParameter();
|
|
|
|
TestFunctionLikeMacro();
|
|
}
|
|
}
|