Doing C code unit testing on a shoestring: Part 2- Code coverage analysis
Assume for a moment that all of the functions in your program are written using only if/else statements to control program flow. How do you test it?A test achieves 100% code coverage if and only if every if statement was executed and at least once the condition was false and at least once the condition was true (some people call this "branch coverage").
If you always strive for 100% coverage (as you should), the first condition can be dropped: A test achieves 100% code coverage if and only if the following holds: If an if statement was executed then at least once the condition was false and at least once the condition was true. This can be easily proved by induction on block nestedness level.
If your INSTRUM_IF macro's output uniquely identifies the specific if statement then it is pretty straightforward to analyze the overall test output to see if every if statement reported its condition both true and false at least once. Otherwise, a more involved instrumentation is necessary.
Instrumenting the while
statements
The while
keyword can be replaced in a similar manner. We put in instrum.h:
# ifdef
INSTRUM_WHILE
# define
while(condition)
INSTRUM_WHILE(condition)
#endif
instrum_common.h. >
extern int
instrum_while(const
char *condition_name,
int
condition,
const char
*filename,
int line,
const char
*function_name);
#define
INSTRUM_WHILE(condition) \
while(instrum_while(#condition,
(condition)!=0, \
__FILE__, __LINE__, __FUNCTION__))
An implementation of the function instrum_while may, however, have a peculiarity. There are two idioms, while(1) and while(0) which you may want to treat differently. The first one is a synonym for for(;;) which I don't particularly like but the fact is that some reputable people do use it.
The second one is a part of the do{...}while(0)
construct which is
commonly used on two occasions: in macro definitions to wrap a block
and straight in the code to make the break statements do the work of
the dreaded goto
[end of block]
You might want to instrument while(1) as for(;;)and not instrument while(0) at all. Here is a simple implementation of not instrumenting these idioms:
int
instrum_while(const
char *condition_name,
int
condition,
const char
*filename,
int line,
const char
*function_name)
{
if(strcmp(condition_name,
"0") != 0
&&
strcmp(condition_name, "1") != 0)
{
printf("Loop
cond. %s in function %s
"
" (file %s line %d) is %s\n",
condition_name, function_name,
filename, line,
(condition)?"true":"false");
}
return condition;
}
Of course an implementation like this should be kept in a file which
is not instrumented.


Loading comments... Write a comment