I have a (Class member) function which I wish to avoid app crash due to ambiguity. For that purpose I have added a try catch bock as shown below:
void getGene(unsigned int position){
T val;
try {
val = _genome.at(_isCircular ? position % _genome.size() : position);
}
catch (std::exception& e) {
std::cerr << "Error in [" << __PRETTY_FUNCTION__ << "]: "
<< e.what() << std::endl;
exit(1);
}
return val;
}
Now, I wish to add a Boost unit test, which I thought of doing something like
BOOST_AUTO_TEST_CASE(nonCircularGenome_test){
// set size to 10
test.setSize(10);
// set non circular
test.setNonCircular();
// gene at site # 12 does not exist in a 10-site long genome, must throw an exception
BOOST_CHECK_THROW(test.getGene(12), std::out_of_range);
The problem is, I can't get both these things work. The try-catch block works well in release setup. However, this test works, only if I remove the try-catch block and let the function throw the exception.
What is the best way to get both these things working, so that a user is prompted with correct error on the go, while tests check explicitly on debug? One way is the use #ifdef/#endif DEBUG blocks, but I wish to avoid pre-processor macros.
Thanks in advance,
Nikhil
You seem to be misunderstanding the scope and purpose of exceptions - and perhaps of error handling in general.
First of all, you should define what are the pre-conditions of your function: does getGene() always expect position to be a valid one? Does it expect its clients to never provide invalid positions?
If that is the case, a client that provides an invalid position (even if the client is a test routine) is breaking the contract with the getGene() (in particular, it is breaking its pre-condition), and breaking a contract is undefined behavior by definition. You cannot test undefined behavior, so you should remove your test.
On the other hand, if your function has a wide contract, i.e. it allows the clients to pass in any position (even invalid ones) and (a) throws an exception or (b) returns an error code to communicate failure when the position is invalid, then the exit(1) line should not be there, because you are quitting the program and control is not transferred back to the caller.
One possibility is to re-throw the exception after logging the diagnostic:
T getGene(unsigned int position){
T val;
try {
val = _genome.at(_isCircular ? position % _genome.size() : position);
}
catch (std::exception& e) {
std::cerr << "Error in [" << __PRETTY_FUNCTION__ << "]: "
<< e.what() << std::endl;
throw;
// ^^^^^
}
return val;
}
And if you do not need to print a diagnostic, just let the exception naturally propagate:
T getGene(unsigned int position){
return _genome.at(_isCircular ? position % _genome.size() : position);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With