Remove auto generated exception code from coverage report
Asked Answered
S

1

3

Let's start with a minimal working example:
main.cpp:

#include <iostream>
#include <string>

int main() {
    std::cout << "hello " + std::to_string(42);
    return 0;
}

I compile this code using the following flags:

[g++/clang++] -std=c++11 -g -Og --coverage -Wall -o main main.cpp

clang 4.0.1
gcc 4.8.5.

I get only 50% code coverage, since the compiler generates exception code, which is not executed, as explained in another stackoverflow question.

The problem is that disabling exceptions via -fno-exceptionsis not an option for me. The code I am writing unit tests for uses exceptions, so disabling all of them is not an option.

In order to generate a report I'm using gcovr, in case of clang++ additionally llvm-cov gcovto convert it. But I am not bound to these tools, so if you have other tools that do not show this behaviour please suggest them!

Basically I need a way to compile/write unit tests for this code and get 100% branch / conditional coverage with exceptions enabled. Is there a way?

Stig answered 22/9, 2017 at 14:32 Comment(0)
C
1

Well, I believe your intention is not actually test this small piece of code, but use the concept in a project...

The code you entered throws an exception - bad_alloc is thrown when you have no memory left to store the string that will be created with std::to_string. To be 100% safe, std::to_string should be surrounded with try-catch, where you could handle your exception.

To build a 100% code coverage unit test, you will need to force the exception to happen - in this specific case it is almost impossible to guarantee, since the parameter is a constant number. But, in your project, you probably have some data to be allocated whose size is variable - in this case, you can isolate in your code the methods that allocate memory, to test them separately. Then you pass to these methods, in the test function, a huge amount to be allocated to evaluate what you have put on your catch block (and check if you are handling it properly).

For instance, this code should throw the exception, you could use it to inspire yourself when building your tests (source):

// bad_alloc.cpp
// compile with: /EHsc
#include<new>
#include<iostream>
using namespace std;

int main() {
   char* ptr;
   try {
      ptr = new char[(~unsigned int((int)0)/2) - 1];
      delete[] ptr;
   }
   catch( bad_alloc &ba) {
      cout << ba.what( ) << endl;
   }
}

However, if you are not planning to handle all bad_alloc exceptions (or absolutely all exceptions) in your code, there is no way to get 100% coverage - since it won't be 100% covered... Most of the cases, true 100% coverage is unnecessary, though.

Cooncan answered 22/9, 2017 at 15:26 Comment(2)
Wouldn't throw in a 32 bit program, would it? Perhaps use uint64_t...Zared
Also, why the int first?Zared

© 2022 - 2024 — McMap. All rights reserved.