Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The blocks in code coverage with VS2010

I run the C++ code to get code coverage results as is in this post.

#include <iostream>
using namespace std;

int testfunction(int input)
{
    if (input > 0) {
        return 1;
    }
    else {
        return 0;
    }
}

int main()
{
    testfunction(-1);
    testfunction(1);
}

enter image description here

The code coverage result says there are three blocks in the main(), and four blocks in the testfunction(). What does the block mean? How does are there the 3/4 blocks in main/testfunction?

ADDED

When I modified the code as follows,

int main()
{
    testfunction(1);
    testfunction(1);
}

or as follows

int main()
{
    testfunction(-1);
    testfunction(-1);
}

I have this result.

enter image description here

And it seems that the testfunction() has four blocks.

  1. the function entry
  2. if block
  3. else block
  4. condition

I got hints from this post.

like image 855
prosseek Avatar asked Feb 10 '11 14:02

prosseek


People also ask

What is block coverage?

A block policy is an all-risk insurance policy providing coverage against risks faced by goods transported or stored by third parties. Commonly found in commercial insurance, a block policy is designed to protect businesses from property damage.

How do I see the code coverage code in Visual Studio?

On the Test menu, select Analyze Code Coverage for All Tests. You can also run code coverage from the Test Explorer tool window. Show Code Coverage Coloring in the Code Coverage Results window. By default, code that is covered by tests is highlighted in light blue.

What is the best updated code coverage tool?

#1) Parasoft JTest Its report provides a good picture of code covered and thereby minimizes risks. Key Features: It is used for Java-based applications. It is a multi-tasking tool which includes Data flow analysis, Unit testing, Static analysis, runtime error detection, code coverage testing etc.


1 Answers

The technical term for a block in code coverage is basic block. To crib directly from the Wikipedia entry:

The code in a basic block has one entry point, meaning no code within it is the destination of a jump instruction anywhere in the program, and it has one exit point, meaning only the last instruction can cause the program to begin executing code in a different basic block. Under these circumstances, whenever the first instruction in a basic block is executed, the rest of the instructions are necessarily executed exactly once, in order.

A basic block is important in code coverage because we can insert a probe at the beginning of the basic block. When this probe is hit, we know that all of the following instructions in that basic block will be executed (due to the properties of a basic block).

Unfortunately, with compilers (and especially with optimizations), it's not always apparent how source code maps to basic blocks. The easiest way to tell is to look at the generated assembly. For example, let's look at your original main & testfunction:

For main, I see the assembly below (interleaved with the original source). Similarly to what Peter does here, I have noted where the basic blocks start.

int main()
{
013B2D20  push        ebp                       <--- Block 0 (initial)
013B2D21  mov         ebp,esp  
013B2D23  sub         esp,40h  
013B2D26  push        ebx  
013B2D27  push        esi  
013B2D28  push        edi  
    testfunction(-1);
013B2D29  push        0FFFFFFFFh  
013B2D2B  call        testfunction (013B10CDh)  
013B2D30  add         esp,4                     <--- Block 1 (due to call)
    testfunction(1);
013B2D33  push        1  
013B2D35  call        testfunction (013B10CDh)  
013B2D3A  add         esp,4                     <--- Block 2 (due to call)
}
013B2D3D  xor         eax,eax  
013B2D3F  pop         edi  
013B2D40  pop         esi  
013B2D41  pop         ebx  
013B2D42  mov         esp,ebp  
013B2D44  pop         ebp  
013B2D45  ret  

We see that main has three basic blocks: one initial block, and the other two because of the function calls. Looking at the code, this seems reasonable. testfunction is a little tougher. Just looking at the source, there appears to be three blocks:

  1. The entry to the function and logic test (input > 0)
  2. The condition true branch (return 1)
  3. The condition false branch (return 0)

However, because of the actual generated assembly, there are four blocks. I'm assuming you built your code with optimizations disabled. When I build with VS2010 in the Debug configuration (optimizations disabled), I see the following disassembly for testfunction:

int testfunction(int input)
{
013B2CF0  push        ebp                         <--- Block 0 (initial)
013B2CF1  mov         ebp,esp  
013B2CF3  sub         esp,40h  
013B2CF6  push        ebx  
013B2CF7  push        esi  
013B2CF8  push        edi  
    if (input > 0) {
013B2CF9  cmp         dword ptr [input],0  
013B2CFD  jle         testfunction+18h (013B2D08h)  
        return 1;
013B2CFF  mov         eax,1                        <--- Block 1 (due to jle branch)
013B2D04  jmp         testfunction+1Ah (013B2D0Ah)  
    }
    else {
013B2D06  jmp         testfunction+1Ah (013B2D0Ah) <--- Not a block (unreachable code)
        return 0;
013B2D08  xor         eax,eax                      <--- Block 2 (due to jmp branch @ 013B2D04)
    }
}
013B2D0A  pop         edi                          <--- Block 3 (due to being jump target from 013B2D04)
013B2D0B  pop         esi  
013B2D0C  pop         ebx  
013B2D0D  mov         esp,ebp  
013B2D0F  pop         ebp  
013B2D10  ret  

Here, we have four blocks:

  1. The entry to the function
  2. The condition true branch
  3. The condition false branch
  4. The shared function epilog (cleaning up the stack and returning)

Had the compiler duplicated the function epilog in both the condition true and condition false branches, you would only see three blocks. Also, interestingly, the compiler inserted a spurious jmp instruction at 013B2D06. Because it's unreachable code, it's not treated as a basic block.

In general, all of this analysis is overkill since the overall code coverage metric will tell you what you need to know. This answer was just to highlight why the number of blocks isn't always obvious or what's expected.

like image 130
Chris Schmich Avatar answered Sep 21 '22 06:09

Chris Schmich