diff --git a/tests/test_errors.cpp b/tests/test_errors.cpp new file mode 100644 index 0000000..41adbf5 --- /dev/null +++ b/tests/test_errors.cpp @@ -0,0 +1,77 @@ +#include "gtest/gtest.h" +#include "src/errors.cpp" +#include +#include +#include + +// 信号处理工具,用于捕获程序崩溃 +static jmp_buf jump_buffer; + +void signal_handler(int sig) { + (void)sig; + longjmp(jump_buffer, 1); +} + +// 测试夹具类 +class ErrorsTest : public ::testing::Test { +protected: + void SetUp() override { + // 保存旧的信号处理器 + old_sigsegv_handler = std::signal(SIGSEGV, signal_handler); + old_sigabrt_handler = std::signal(SIGABRT, signal_handler); + } + + void TearDown() override { + // 恢复旧的信号处理器 + std::signal(SIGSEGV, old_sigsegv_handler); + std::signal(SIGABRT, old_sigabrt_handler); + } + + // 执行一个预期会崩溃的函数,并验证它确实崩溃了 + void ExpectFunctionCrashes(void (*func)()) { + if (setjmp(jump_buffer) == 0) { + // 第一次进入,执行预期会崩溃的函数 + func(); + // 如果函数没有崩溃,测试失败 + FAIL() << "Expected function to crash, but it did not."; + } else { + // 函数崩溃,被信号处理器跳转回来,测试通过 + SUCCEED(); + } + } + +private: + using SignalHandler = void (*)(int); + SignalHandler old_sigsegv_handler; + SignalHandler old_sigabrt_handler; +}; + +// 测试 test_null_pointer 函数 +TEST_F(ErrorsTest, test_null_pointer_CrashesOnDereference) { + // 这个函数应该因为解引用空指针而崩溃 + ExpectFunctionCrashes(test_null_pointer); +} + +// 测试 test_array_out_of_bounds 函数 +TEST_F(ErrorsTest, test_array_out_of_bounds_CrashesOnOutOfBoundsAccess) { + // 这个函数应该因为数组越界访问而崩溃 + ExpectFunctionCrashes(test_array_out_of_bounds); +} + +// 测试 test_uninitialized_var 函数 +// 注意:使用未初始化变量的行为是未定义的,它可能崩溃,也可能不崩溃。 +// 因此,这个测试只是执行函数,不强制断言其行为。 +// 在实际测试中,我们可能使用工具(如 Valgrind, MSAN)来检测此类错误。 +TEST_F(ErrorsTest, test_uninitialized_var_UndefinedBehavior) { + // 由于行为未定义,我们只执行函数,不进行断言。 + // 在启用了未初始化变量检测的构建中,这可能会触发错误。 + test_uninitialized_var(); + // 没有断言,因为行为未定义。 + // 这个测试的存在是为了记录和覆盖这个函数。 +} + +// 主函数(如果单独编译测试文件需要) +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}