3

I'm using Visual Studio 2015 Update 3.

I am failing to get 100% code coverage on this simple Unit Test:

TEST_METHOD(New)
{
    int* test = new int(4); //shows the line as partially covered
    int* test2 = new int;   //shows line as 100% covered
}

This happens if the statements are in the code called by the test function as well.

The only setting changed from the default for the project is the /profile switch, which is necessary to get any code coverage to work in the first place.

I noticed that new when used without an initializer shows 100% coverage, but for classes I usually initialize them right away and I would like to find a way to do it without reducing the code coverage.

Code Disassembly

                int* test = new int(4); //shows the line as partially covered
0F951D53  push        4  
0F951D55  call        operator new (0F9512B2h)  
0F951D5A  add         esp,4  
0F951D5D  mov         dword ptr [ebp-0ECh],eax  
0F951D63  cmp         dword ptr [ebp-0ECh],0  
0F951D6A  je          UnitTest1::UnitTest1::New+56h (0F951D86h)  
0F951D6C  mov         eax,dword ptr [ebp-0ECh]  
0F951D72  mov         dword ptr [eax],4  
0F951D78  mov         ecx,dword ptr [ebp-0ECh]  
0F951D7E  mov         dword ptr [ebp-100h],ecx  
0F951D84  jmp         UnitTest1::UnitTest1::New+60h (0F951D90h)  
0F951D86  mov         dword ptr [ebp-100h],0  
0F951D90  mov         edx,dword ptr [ebp-100h]  
0F951D96  mov         dword ptr [test],edx  
            int* test2 = new int;   //shows line as 100% covered
0F951D99  push        4  
0F951D9B  call        operator new (0F9512B2h)  
0F951DA0  add         esp,4  
0F951DA3  mov         dword ptr [ebp-0F8h],eax  
0F951DA9  mov         eax,dword ptr [ebp-0F8h]  
0F951DAF  mov         dword ptr [test2],eax  

Looking at the code, I'm guessing the jmp statements cause the code coverage analysis tool to see some statements as not hit.

meneldal
  • 1,717
  • 1
  • 21
  • 30

1 Answers1

2

You seem to have an option which means that new always behaves as new(nothrow) (in other words, new returns nullptr if the allocation fails).

The assembly is checking if operator new has returned nullptr (and if so, not storing 4 at the returned address). You need to test the case where the allocation failed in order to have complete coverage. In C++, the assembly looks like:

    int * test;
    int * tmp = operator new(sizeof(int));
    if (tmp != nullptr) {
        *tmp = 4;
        test = tmp;
    } else {
        test = nullptr;
    }

Edit

Ah ha! In this blog post Microsoft explain that the generated code for new has been testing for a null return, just in case you link in the nothrow version. With VC2015, they have provided an option to say "don't bother doing that, new will throw, it will never return nullptr.

So, to avoid the unnecessary branch, add: /Zc:throwingNew to the compilation options. (This will also help performance generally.)

  • So there's no concise way of making it mark it as fully covered? I'm already testing the case where `nullptr` is sent to the functions I'm using anyway. – meneldal Jul 11 '17 at 09:00
  • Thank you, I've searched the Microsoft website but couldn't find this, your Google-fu is on a different level. Accepted your answer. – meneldal Jul 11 '17 at 09:32