I'm using gtest to write some unit tests for exception handling code. As a simple example, let's say I want my program to abort
on any unhandled exception, so I create the following test:
TEST_F(myFixture, myTest)
{
std::set_terminate([](){std::abort(); });
EXPECT_DEATH(throw std::runtime_error("terminate"), ".*");
}
I would expect this to succeed, since abort
should be called on the program. However, my actual result is:
error: Death test: throw std::runtime_error("terminate")
Result: threw an exception.
Error msg:[ DEATH ]
[ DEATH ] main.cpp(122):: Caught std::exception-derived exception escaping the death test statement. Exception message: terminate[ DEATH ]
I think gtest's exception handlers are getting in the way. I've tried disabling them using the GTEST_CATCH_EXCEPTIONS
environment variable, and the --gtest_catch_exceptions=0
command line flag as mentioned in the advanced guide, but I get the same result.
Am I doing something wrong, or is "death by exception" not something gtest can test for?
Am I doing something wrong, or is "death by exception" not something gtest can test for?
What you're doing is wrong, because "death by exception" is not something gtest can test for.
EXPECT_DEATH(statement, regex);
verifies that statement
calls abort
or exit
and causes output matching
regex
. The statement throw std::runtime_error("terminate")
doesn't call
abort
or exit
, as can be seen from the possibility of catching any exception in the program and letting it carry on. If an exception is not caught then the runtime library will call terminate
, ending the program one way or another. But this outcome is not determined by any throw
statement.
See the documentation of death-tests, in particular:
...any test that checks that a program terminates (except by throwing an exception) in an expected fashion is also a death test.
Note that if a piece of code throws an exception, we don't consider it "death" for the purpose of death tests, as the caller of the code could catch the exception and avoid the crash. If you want to verify exceptions thrown by your code, see Exception Assertions.
and:
Note that a death test only cares about three things:
- does statement abort or exit the process? ...
I appreciate you may be oversimplfying your real issue here but you
hardly need to test that unhandled exceptions will result in terminate
being called, or that terminate
will call the operative terminate-
handler, unless it is your daunting duty to test the implementation of
your compiler and standard library. Maybe more of the real issue should
be aired?
Later
my problem with this is my program doesn't (or shouldn't) carry on. It should abort via the termination handler.
It should, but per documentation the expectation that your program should
not carry on is not tested by EXPECT_DEATH
on any throw
statement, because no throw
statement terminates the program.
What I really want to test is that the behavior of my set_terminate handler is correct.
The behaviour of your set_terminate
handler is correct if any only if,
having set that handler, a call to std::terminate()
has the outcome you
expect. This question is independent of any throw
statement and
you may test it like:
#include <iostream>
#include <gtest/gtest.h>
#include <exception>
TEST(the_end, is_nigh)
{
std::set_terminate([](){std::cout << "Goodbye cruel world\n", std::abort(); });
EXPECT_DEATH(std::terminate(), ".*");
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
which produces:
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from the_end
[ RUN ] the_end.is_nigh
Goodbye cruel world
[ OK ] the_end.is_nigh (172 ms)
[----------] 1 test from the_end (172 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (172 ms total)
[ PASSED ] 1 test.
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