cdemo/tests/test_errors.cpp

96 lines
3.6 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "gtest/gtest.h"
#include "src/errors.h"
#include <iostream>
#include <csetjmp>
#include <csignal>
// 全局跳转点,用于处理信号
static std::jmp_buf jump_buffer;
// 信号处理函数
static void signal_handler(int sig) {
std::longjmp(jump_buffer, sig);
}
// 测试夹具类
class ErrorsTest : public ::testing::Test {
protected:
// 保存旧的信号处理器
struct sigaction old_action_segv;
struct sigaction old_action_abrt;
void SetUp() override {
// 为 SIGSEGV 和 SIGABRT 设置新的信号处理器
struct sigaction new_action;
new_action.sa_handler = signal_handler;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGSEGV, &new_action, &old_action_segv);
sigaction(SIGABRT, &new_action, &old_action_abrt);
}
void TearDown() override {
// 恢复旧的信号处理器
sigaction(SIGSEGV, &old_action_segv, nullptr);
sigaction(SIGABRT, &old_action_abrt, nullptr);
}
};
// 测试 test_null_pointer 函数会触发段错误
TEST_F(ErrorsTest, test_null_pointerTriggersSegFault) {
// 设置跳转点,如果发生信号则跳转回这里
int sig = setjmp(jump_buffer);
if (sig == 0) {
// 尝试调用会触发错误的函数
test_null_pointer();
// 如果执行到这里,说明没有触发信号,测试失败
FAIL() << "Expected test_null_pointer to cause a segmentation fault.";
} else {
// 检查捕获到的信号是否是预期的 SIGSEGV
EXPECT_EQ(sig, SIGSEGV) << "Expected SIGSEGV, but got signal: " << sig;
}
}
// 测试 test_array_out_of_bounds 函数会触发段错误
TEST_F(ErrorsTest, test_array_out_of_boundsTriggersSegFault) {
int sig = setjmp(jump_buffer);
if (sig == 0) {
test_array_out_of_bounds();
FAIL() << "Expected test_array_out_of_bounds to cause a segmentation fault.";
} else {
// 数组越界通常也会导致 SIGSEGV
EXPECT_EQ(sig, SIGSEGV) << "Expected SIGSEGV, but got signal: " << sig;
}
}
// 测试 test_uninitialized_var 函数的行为是未定义的
// 我们无法可靠地测试未定义行为,但可以验证函数调用本身不会导致程序崩溃(如段错误)
// 注意:这个测试可能通过,也可能失败,因为行为是未定义的。
// 更安全的做法是验证函数可以被调用,而不对输出做任何断言。
TEST_F(ErrorsTest, test_uninitialized_varDoesNotCrash) {
// 设置跳转点捕获致命信号
int sig = setjmp(jump_buffer);
if (sig == 0) {
// 调用函数。由于使用未初始化变量是未定义行为,
// 它可能做任何事情,包括不崩溃。
// 我们只测试它不会触发我们捕获的信号SIGSEGV, SIGABRT
test_uninitialized_var();
// 如果执行到这里,说明没有触发 SIGSEGV 或 SIGABRT。
// 对于未定义行为,我们无法做出更多有意义的断言。
SUCCEED();
} else {
// 如果捕获到信号,记录它,但这不是必然的预期。
// 我们将此视为测试通过的一种可能路径,因为行为未定义。
// 更严谨的做法是标记测试为不可靠或跳过。
// 这里我们选择不使测试失败,仅记录。
std::cout << "Note: test_uninitialized_var triggered signal " << sig << " (behavior is undefined)." << std::endl;
}
}
// 主函数(通常由 gtest_main 提供,这里显式写出以确保可编译)
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}