#include "gtest/gtest.h" #include "src/errors.cpp" #include #include #include // 用于捕获信号和异常的全局变量 static std::jmp_buf jump_buffer; static volatile std::sig_atomic_t gSignalStatus; // 信号处理函数 void signal_handler(int signal) { gSignalStatus = signal; std::longjmp(jump_buffer, 1); } namespace { // 测试类,用于设置和恢复信号处理器 class SignalGuard { public: SignalGuard(int sig, void (*handler)(int)) : m_sig(sig), m_old_handler(std::signal(sig, handler)) {} ~SignalGuard() { std::signal(m_sig, m_old_handler); } private: int m_sig; void (*m_old_handler)(int); }; // 测试 test_null_pointer 函数 TEST(ErrorsTest, TestNullPointerTriggersSignal) { // 安装 SIGSEGV 信号处理器 SignalGuard guard(SIGSEGV, signal_handler); gSignalStatus = 0; // 使用 setjmp/longjmp 来捕获信号后的跳转 if (setjmp(jump_buffer) == 0) { // 尝试执行会触发段错误的函数 test_null_pointer(); // 如果执行到这里,说明没有触发信号,测试失败 FAIL() << "Expected test_null_pointer to cause a segmentation fault"; } else { // 成功捕获到信号 EXPECT_EQ(gSignalStatus, SIGSEGV); } } // 测试 test_array_out_of_bounds 函数 TEST(ErrorsTest, TestArrayOutOfBoundsTriggersSignal) { // 安装 SIGSEGV 信号处理器 SignalGuard guard(SIGSEGV, signal_handler); gSignalStatus = 0; if (setjmp(jump_buffer) == 0) { test_array_out_of_bounds(); FAIL() << "Expected test_array_out_of_bounds to cause a segmentation fault"; } else { EXPECT_EQ(gSignalStatus, SIGSEGV); } } // 测试 test_uninitialized_var 函数 // 注意:未初始化变量的行为是未定义的,可能不会崩溃,但结果不可预测。 // 我们无法可靠地测试其具体行为,但可以验证函数调用本身不会导致程序终止(如信号)。 // 然而,为了演示,我们仍然运行它,但不对其输出做任何断言,因为它是未定义的。 TEST(ErrorsTest, TestUninitializedVarRunsWithoutCrash) { // 这个测试主要是为了确保函数可以被调用,而不导致程序崩溃(尽管行为未定义)。 // 由于未初始化变量的值是未定义的,我们无法断言其具体行为。 // 在某些配置下(如调试模式),变量可能被初始化为0,但这不是保证的。 // 因此,我们只调用函数,不进行断言。 // 注意:这实际上不是一个好的单元测试,因为它没有验证任何确定的行为。 // 它只是为了演示如何“测试”一个具有未定义行为的函数。 // 在实际项目中,这样的函数应该被修复,而不是被测试。 test_uninitialized_var(); // 如果程序执行到这里,说明没有崩溃,测试通过。 // 我们无法对输出做任何有意义的断言。 SUCCEED(); } // 额外的测试:验证正常数组访问不会崩溃(作为对比) TEST(ErrorsTest, TestNormalArrayAccessDoesNotCrash) { int arr[3] = {1, 2, 3}; EXPECT_EQ(arr[0], 1); EXPECT_EQ(arr[1], 2); EXPECT_EQ(arr[2], 3); // 访问有效索引,不应崩溃 SUCCEED(); } // 额外的测试:验证已初始化的指针解引用不会崩溃(作为对比) TEST(ErrorsTest, TestValidPointerDereferenceDoesNotCrash) { int value = 42; int* p = &value; EXPECT_EQ(*p, 42); SUCCEED(); } // 额外的测试:验证已初始化的变量行为可预测 TEST(ErrorsTest, TestInitializedVarBehaviorIsPredictable) { int val = 15; // 明确初始化 if (val > 10) { SUCCEED(); // 条件为真,符合预期 } else { FAIL() << "Initialized variable should behave predictably"; } } }