Coverage levels

The product provides coverage information for various levels of statements, decisions, loops, calls, conditions.

Block coverage

When running the code coverage feature on C source code, the following coverage types are analyzed.
  • Statement blocks (simple blocks): Simple blocks are the main blocks of the C function, introduced by decision statements:
    • THEN and ELSE FOR IF statements
    • FOR, WHILE and DO ... WHILE blocks
    • Non-empty blocks introduced by switch case or default statements.
    • True and false outcomes of ternary expressions (<expression> ? <expression> : <expression>).
    • Blocks following a potentially terminal statement.

    Each simple block is a branch. Every C function contains at least one simple block corresponding to its main body.

  • Decisions (implicit blocks): Implicit blocks are introduced by an IF statement without an ELSE or a SWITCH statement without a DEFAULT. Each simple block is a branch. Every C function contains at least one simple block corresponding to its main body.

  • Loops (logical blocks): Logical blocks are defined by loop statements FOR, WHILE, and DO ... WHILE.

    A typical FOR or WHILE loop can reach three different conditions:
    • The statement block contained within the loop is executed zero times. The output condition is True from the start
    • The statement block is executed exactly once. The output condition is False, then True the next time
    • The statement block is executed at least twice. The output condition is False at least twice, and becomes True at the end.
    In a DO...WHILE loop, because the output condition is tested after the block has been executed, two further branches are created:
    • The statement block is executed exactly once. The output is condition True the first time.
    • The statement block is executed at least twice. The output condition is False at least once, then True at the end.

Call coverage

Code coverage provides coverage of function or procedure calls by counting as many branches as it encounters function calls while running the program. This type of coverage ensures that all the call interfaces can be shown to have been exercised for each C function, which may be a pass or failure criterion in software integration test phases.

You can exclude specific C functions whose calls you do not want to measure coverage in the configuration settings of the project. This can be useful for C library functions for example.

Condition coverage

For conditions, the following coverage types are analyzed:
  • Basic condition coverage: Conditions are operands of either || or && operators wherever they appear in the body of a C function, IF statements and ternary expressions, and tests for FOR, WHILE, and DO ... WHILE statements even if these expressions do not contain || or && operators.

    Two branches are involved in each condition, causing the sub-condition to be true or false. In a switch statement, one basic condition is associated with every CASE and DEFAULT, whether implicit or not.

    Two branches are enumerated for each condition, and one per CASE or DEFAULT.

  • Modified condition/decision coverage (MC/DC): A modified condition (MC) is defined for each basic condition enclosed in a composition of || or && operators, proving that the condition affects the result of the enclosing composition. For example, in a subset of values affected by the other conditions, if the value of this condition changes, the result of the entire expression changes. Because compound conditions list all possible cases, you must find the two cases that can result in changes to the entire expression. The modified condition is covered only if the two compound conditions are covered.

    You can associate a modified condition with more than one case. Code Coverage calculates matching cases for each modified condition. The number of modified conditions matches the number of Boolean basic conditions in a composition of || and && operators.

  • Multiple condition coverage: A multiple (or compound) condition is one of all the available cases for the || and && logical operator compositions, whenever it appears in a C function. It is defined by the simultaneous values of the enclosed Boolean basic conditions. Remember that the right operand of a || or && operator is not evaluated if the evaluation of the left operand determines the result of the entire expression.

    Code Coverage calculates every available case for each composition. The number of enumerated branches is the number of distinct available cases for each composition of the || or && operators.

  • Forced condition coverage: Forced conditions are multiple conditions in which the instrumentation replaces any occurrence of the || or && logical operators in the code, with | and & binary operators. You can use this coverage type, after evaluating all modified conditions, to make sure that every basic condition has been evaluated. With this forced condition coverage, you can ensure that only the basic condition has changed between two tests.

Function coverage

When analyzing C source code, HCL OneTest Embedded can provide the following function coverage:
  • Procedure entries: Inputs identify the C functions that are executed. One branch is defined per C function.
  • Procedure exits: These include the standard output (if coverable), and all return instructions, exits, and other terminal instructions that are instrumented, as well as the input. At least two branches are defined per C function.

The input is always enumerated, as is the output if it can be covered. If it cannot, it is preceded by a terminal instruction involving returns or an exit. In addition to the terminal instructions provided in the standard definition file, you can define other terminal instructions using the pragma attol exit_instr.

Additional statements

Some statements are identified as terminal, potentially terminal, or non-coverable.

A C statement is terminal if it transfers program control out of sequence (RETURN, GOTO, BREAK, CONTINUE), or if it stops the execution (EXIT). By extension, a decision statement (IF or SWITCH) is terminal if all branches are terminal; that is if the non-empty THEN ... ELSE, CASE, and DEFAULT blocks all contain terminal statements. An IF statement without an ELSE and a SWITCH statement without a DEFAULT are never terminal, because their empty blocks necessarily continue the program sequence.

The following decision statements are potentially terminal if they contain at least one statement that transfers program control out of their sequence (RETURN, GOTO, BREAK, CONTINUE), or that stops the execution (EXIT):
  • IF without an ELSE
  • FOR
  • WHILE or DO ... WHILE

Some C statements are considered non-coverable if they follow either a terminal instruction, a CONTINUE, or a BREAK, and are not a GOTO label. Code coverage detects non-coverable statements during instrumentation and produces a warning message that specifies the source file and line location of each non-coverable statement.

Note: User functions whose purpose is to terminate execution unconditionally are not evaluated. Furthermore, code coverage does not statically analyze exit conditions for loops to check whether they are infinite. As a result, FOR ... WHILE and DO ... WHILE loops are always assumed to be non-terminal, able to resume program control in sequence.