编写死亡测试来验证 std::set_terminate 行为

write death test to verify std::set_terminate behavior

我正在使用 gtest 为异常处理代码编写一些单元测试。作为一个简单的例子,假设我希望我的程序在任何未处理的异常上 abort,所以我创建了以下测试:

TEST_F(myFixture, myTest)
{
    std::set_terminate([](){std::abort(); });

    EXPECT_DEATH(throw std::runtime_error("terminate"), ".*");
}

我希望这会成功,因为应该在程序中调用 abort。然而,我的实际结果是:

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 ]

我认为 gtest 的异常处理程序妨碍了。我尝试使用 GTEST_CATCH_EXCEPTIONS 环境变量和 --gtest_catch_exceptions=0 命令行标志禁用它们,如 the advanced guide 中所述,但我得到了相同的结果。

我做错了什么,还是 "death by exception" 不是 gtest 可以测试的东西?

Am I doing something wrong, or is "death by exception" not something gtest can test for?

你做的是错误的,因为 "death by exception" 不是 gtest 可以测试的东西。

EXPECT_DEATH(statement, regex);

验证 statement 调用 abortexit 并导致输出匹配 regex。语句 throw std::runtime_error("terminate") 不调用 abortexit,从捕获程序中的任何异常并让它继续进行的可能性中可以看出。 如果未捕获到异常,则运行时库将调用terminate,以某种方式结束程序。但是这个结果不是由任何throw语句决定的。

documentation of death-tests, 特别是:

...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.

和:

Note that a death test only cares about three things:

  1. does statement abort or exit the process? ...

我很感激你在这里可能过于简单化了你的实际问题,但你 几乎不需要测试未处理的异常会导致 terminate 被调用,或者 terminate 将调用操作终止- 处理程序,除非您有艰巨的职责来测试 你的编译器和标准库。也许更多的真正的问题应该 播出?

以后

my problem with this is my program doesn't (or shouldn't) carry on. It should abort via the termination handler.

应该,但是根据文档,您的程序应该 未进行 未通过 EXPECT_DEATH 任何 throw 声明测试,因为没有 throw 语句终止程序。

What I really want to test is that the behavior of my set_terminate handler is correct.

你的 set_terminate 处理程序的行为是正确的,如果有的话,只有, 设置该处理程序后,调用 std::terminate() 的结果是 预计。这个问题独立于任何 throw 陈述并且 你可以这样测试它:

#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();
}

产生:

[==========] 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.