diff --git a/tests/test_errors.cpp b/tests/test_errors.cpp new file mode 100644 index 0000000..eb698de --- /dev/null +++ b/tests/test_errors.cpp @@ -0,0 +1,95 @@ +#include "gtest/gtest.h" +#include "src/errors.h" +#include +#include +#include + +// 全局跳转点,用于处理信号 +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(); +}