#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); } // 测试空指针解引用 TEST(ErrorsTest, TestNullPointerTriggersCrash) { // 设置信号处理器来捕获段错误(SIGSEGV) struct sigaction sa_old; struct sigaction sa_new; sa_new.sa_handler = signal_handler; sigemptyset(&sa_new.sa_mask); sa_new.sa_flags = 0; // 保存旧的信号处理器并安装新的 sigaction(SIGSEGV, &sa_new, &sa_old); // 使用 setjmp/longjmp 来捕获崩溃 if (setjmp(jump_buffer) == 0) { // 尝试调用会崩溃的函数 test_null_pointer(); // 如果执行到这里,说明没有崩溃,测试失败 FAIL() << "Expected test_null_pointer() to cause a segmentation fault"; } else { // 成功捕获到崩溃,测试通过 SUCCEED(); } // 恢复旧的信号处理器 sigaction(SIGSEGV, &sa_old, nullptr); } // 测试数组越界访问 TEST(ErrorsTest, TestArrayOutOfBoundsTriggersCrash) { // 设置信号处理器来捕获段错误(SIGSEGV) struct sigaction sa_old; struct sigaction sa_new; sa_new.sa_handler = signal_handler; sigemptyset(&sa_new.sa_mask); sa_new.sa_flags = 0; // 保存旧的信号处理器并安装新的 sigaction(SIGSEGV, &sa_new, &sa_old); // 使用 setjmp/longjmp 来捕获崩溃 if (setjmp(jump_buffer) == 0) { // 尝试调用会崩溃的函数 test_array_out_of_bounds(); // 如果执行到这里,说明没有崩溃,测试失败 FAIL() << "Expected test_array_out_of_bounds() to cause a segmentation fault"; } else { // 成功捕获到崩溃,测试通过 SUCCEED(); } // 恢复旧的信号处理器 sigaction(SIGSEGV, &sa_old, nullptr); } // 测试未初始化变量使用 // 注意:使用未初始化变量的行为是未定义的,可能不会立即崩溃 // 我们主要验证函数可以执行而不抛出异常(尽管行为未定义) TEST(ErrorsTest, TestUninitializedVarExecutesWithoutCrash) { // 设置信号处理器来捕获可能的崩溃 struct sigaction sa_old; struct sigaction sa_new; sa_new.sa_handler = signal_handler; sigemptyset(&sa_new.sa_mask); sa_new.sa_flags = 0; // 保存旧的信号处理器并安装新的 sigaction(SIGSEGV, &sa_new, &sa_old); // 使用 setjmp/longjmp 来捕获可能的崩溃 if (setjmp(jump_buffer) == 0) { // 尝试调用函数 test_uninitialized_var(); // 如果执行到这里,说明没有崩溃 // 对于未初始化变量的使用,行为是未定义的,但通常不会立即崩溃 SUCCEED(); } else { // 如果捕获到崩溃,也记录但不算失败(因为行为未定义) ADD_FAILURE() << "test_uninitialized_var() caused a crash (undefined behavior)"; } // 恢复旧的信号处理器 sigaction(SIGSEGV, &sa_old, nullptr); } // 边界条件测试:验证这些错误函数确实存在缺陷 // 这个测试验证正常代码不会崩溃 TEST(ErrorsTest, NormalCodeDoesNotCrash) { // 正常的指针使用 int value = 42; int* p = &value; EXPECT_EQ(*p, 42); // 正常的数组访问 int arr[3] = {1, 2, 3}; EXPECT_EQ(arr[0], 1); EXPECT_EQ(arr[1], 2); EXPECT_EQ(arr[2], 3); // 正常的变量初始化 int val = 5; if (val > 10) { FAIL() << "This should not execute"; } else { SUCCEED(); } } // 特殊场景:验证这些是真正的错误模式 TEST(ErrorsTest, ErrorPatternsAreDetected) { // 这些测试验证了错误模式的存在 // 在实际项目中,应该修复这些错误而不是测试它们 // 测试1:空指针解引用是严重错误 EXPECT_DEATH(test_null_pointer(), ".*") << "Null pointer dereference should cause program termination"; // 测试2:数组越界是严重错误 EXPECT_DEATH(test_array_out_of_bounds(), ".*") << "Array out of bounds should cause program termination"; // 注意:test_uninitialized_var 可能不会导致立即崩溃, // 所以不使用 EXPECT_DEATH 测试它 } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }