Doing C code unit testing on a shoestring: Part 2- Code coverage analysis

Ark Khasin, MacroExpressions

September 18, 2007

Ark Khasin, MacroExpressions

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

<>And of course a mutatis mutandis entry is added to the instrumentation specific header such as
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.

< Previous
Page 1 of 5
Next >

Loading comments...

Most Commented

Parts Search Datasheets.com

KNOWLEDGE CENTER