Procedure
Inputs, Outputs and Returns, and Terminal Instructions (C++/Java)
Source-code coverage consists of
identifying which portions of a program are
executed or not during a given test case. Source-code coverage is
recognized as one of
the most effective ways of assessing the efficiency of the
test cases applied to a
software application.
When not explicitly mentioned
coverage rules are valid for all the languages.
When analyzing C/C++/Java source
code, Code Coverage can provide the following block
coverage:
Statement blocks are the
C/C++/Java method blocks, blocks introduced by control
instructions:
Java Example
public class StatementBlocks
{
public static void func( String _message )
throws UnsupportedOperationException
{
throw new UnsupportedOperationException(_message);
}
throws Exception
{
try
{
if ( false )
{
func(
"Hello" );
}
else
{
throw new Exception("bad luck");
}
}
catch ( UnsupportedOperationException _E )
{
System.out.println( _E.toString() );
}
catch ( Exception _E )
{
System.out.println( _E.toString() );
throw _E ;
} //potentially terminal statement
return ; //sequence block
}
}
C++ Example
int main ( ) /* -
BLOCK */
{
try
{
if ( 0 )
{
func ( "Hello" );
}
else
{
throw UnLucky ( );
}
}
catch ( Overflow & o ) {
cout << o.String << '\n';
}
catch ( UnLucky & u ) {
throw u;
} /* potentially terminal statement */
return 0; /* sequence block */
}
Each simple block is a branch.
Every C++/Java function/method contains at least one simple block
corresponding to its main body.
Implicit blocks are introduced by
IF statements without an ELSE statement, and a
SWITCH statement without a DEFAULT
statement.
Java Example
public class MathOp
{
static final int WHITE=0;
static final int LIGHTGRAY=1;
static final int RED=2;
static final int PINK=3;
static final int BLUE=4;
static final int GREEN=5;
// power
of 10
public static int powerOf10( int _value, int _max )
{
int result = _value, i;
if(
_value==0 ) return 0; //implicit else
for(
i = 0; i < 10; i++ )
{
result = ( _max / 10 ) < result ? 10*result :
_max ;
}
return result;
}
// Near color function
int nearColor( int
_color )
{
{
case
WHITE:
case
LIGHTGRAY:
return WHITE ;
case
RED:
case
PINK:
return RED;
//implicit default:
}
return _color ;
}
}
Each implicit block represents a
branch.
Since the sum of all possible
decision paths includes implicit blocks as well as simple
blocks, reports provide the total number of simple and implicit
blocks as a figure and
a percentage after the term decisions.
For C: Code Coverage places this information in the
Decisions report.
Three branches are created in a
FOR or WHILE loop:
For C++/Java:
Two
branches are created in a DO/WHILE loop, as the output condition is
tested after the block has been executed:
For C:
In a
DO...WHILE loop, because the output condition is tested after the block has
been executed, two further branches are created:
Java Example
public class LogicalBlocks
{
public static int tryFiveTimes()
{
int result, i=0;
while ( ( ( result=resourcesAvailable() )<= 0)
&& ( ++i
< 5 ) );
// while define 3 logical blocks
return result;
}
public static int resourcesAvailable()
{
}
public static int _free_resources_=0;
public static void
main( String[] argv )
{
//first call: '0 loop' block is reach
_free_resources_=1;
tryFiveTimes();
//second call: '1 loop' blocks are reach
_free_resources_=0;
tryFiveTimes();
//third call: '2 loops or more' blocks are reach
_free_resources_=-10;
tryFiveTimes();
}
}
When analyzing source code, PurifyPlus for Linux can provide the following function/Unit/Method coverage:
Inputs identify the C/C++/Java
methods executed.
Java Example
public class Inputs
{
public static int method()
{
return 5;
}
public static void
main( String[] argv )
{
System.out.println("Value:"+method());
}
}
C Example
/*
Factorial function */
/*
-proc */
int factorial ( int a )
{
if
( a > 0 ) return a * factorial ( a - 1 );
else
return 1;
}
One branch per C/C++/Java method
is defined.
These include the standard output
(if coverable), all return instructions, and calls to
exit(), abort(), or terminate(), as well as the input.
Java Example
public class InputsOutputsAndReturn
{
public static void
method0( int _selector )
{
if
( _selector < 0 )
{
return ;
}
public static int method1( int _selector )
{
switch( _selector )
{
case
1: return 0;
case
2: break;
case
3: case 4: case 5: return 1;
}
return (_selector/2);
}
public static void
main( String[] argv )
{
method0( 3 );
System.out.println("Value:"+method1(
5 ));
System.exit( 0
);
}
}
At least two branches per
C/C++/Java method are defined. The input is always enumerated,
as is the output if it can be covered.
For C++ : If it cannot, it is preceded by a terminal
instruction
involving returns or by a call to exit(), abort(), or terminate().
For C: If it
cannot, it is preceded by a terminal instruction involving returns or an exit.
The following decision statements
are potentially terminal if they contain at least one
statement that transfers program control out of its sequence
(RETURN, THROW,
GOTO, BREAK, CONTINUE) or that
terminates the execution (EXIT).
Java
A Java statement is non coverable if
the statement can never possibly be executed.
Code Coverage detects non-coverable
statements during instrumentation and
produces an error message that specifies the source file and line location
of each noncoverable
statement.
C++:
A C++ statement is non-coverable if
the statement can never possibly be executed.
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.
C:
Some
C statements are considered non coverable if they follow 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.
Consider a text Coverage summary as follows:
FileName.cpp:
int main (int,
char **) :
Statement blocks
............ 0.0% (0/14)
/then/do, line 57
/then, line 56
/seq, line 64
/then/do, line 68
/then, line 67
/else, line 72
/try/do, line 79
/try, line 78
/catch/do, line 90
/catch, line 89
/try, line 97
/catch/do, line 103
/catch, line 102
/, line 49
Implicit blocks
............. 0.0% (0/1)
/else, line 59
Decisions
................... 0.0% (0/15)
Loops
....................... 0.0% (0/10)
/then/do/1, line 57
/then/do/2+, line 57
/then/do/1, line 68
/then/do/2+, line 68
/try/do/1, line 79
/try/do/2+, line 79
/catch/do/1, line 90
/catch/do/2+, line 90
/catch/do/1, line 103
/catch/do/2+, line 103
This report shows for each function found in the source file the coverage rate (here, the code is not covered at all).
The
percentage is calculated by dividing the available blocks by the number of the
covered ones.
Here, we have 14 Statement blocks, of which none was hit.
After this Block summary, every uncovered block is mentioned, identified by its nature.
Whithin a then statement, there is a do block: /then/do . For each block, the line number of the source file is referenced.
A simple '/' denotes the root block.
Because the sum of all possible decision paths includes implicit blocks as well as statement blocks, reports provide the total number of simple and implicit blocks as a
figure and as a percentage. Code Coverage places this information in the Decisions report.
A loop is considered as covered, if it was executed once without entering into it (for if or for loops only), and entered once ("1"),
and repeated once or more times ("2+").
Here another Coverage example:
void alma.scheduling.planning_mode_sim.simulator.ControlSimulator.initialize() :
Hit ......................... yes
Functions and exits ......... 100.0% (2/2)
Statement blocks ............ 66.7% (2/3)
/catch, line 100
Implicit blocks ............. none
Decisions ................... 66.7% (2/3)
Loops ....................... 33.3% (1/3)
/try/for/0, line 94
/try/for/1, line 94
In this coloured code not covered lines are listed in red.
85 public void initialize() throws ComponentLifecycleException { 86 super.initialize(); 87 try { 88 clock = (ClockSimulator)m_containerServices.getComponent(Container.CLOCK); 89 //weather = new WeatherModel (); 90 // There are no subarrays and all antennas are idle. 91 subarray = new ArrayList (); 92 int numberAntennas = data.getInt(Tag.numberAntennas); 93 antennaList = new Antenna [numberAntennas]; 94 for (int i = 0; i < numberAntennas; ++i) { 95 antennaList[i] = new Antenna (i); 96 } 97 archive = (ArchiveSimulator)m_containerServices.getComponent(Container.ARCHIVE); 98 setUpTimeInSec = data.getSetUpTimeInSec(); 99 changeProjectTimeInSec = data.getChangeProjectTimeInSec(); 100 } catch (Exception err) { 101
m_state.setState(ComponentState.ERROR); 102
m_logger.severe("Control.error " +
err.toString()); 103
throw new ComponentLifecycleException("Control " + Level.SEVERE + " " + err.toString()); 104 } |
The "seq" means that
although the line belongs to the same block as another, between the two lines
of the block there is a potentially terminal instruction. Example:
int
divide (int a, int b) return (result); |