From a3e1425ac21ec3157ba1d0a3172477efa1ae1197 Mon Sep 17 00:00:00 2001 From: lids <1713278948@qq.com> Date: Wed, 15 Apr 2026 16:58:51 +0800 Subject: [PATCH] =?UTF-8?q?AI=20=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_errors.cpp | 141 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 tests/test_errors.cpp diff --git a/tests/test_errors.cpp b/tests/test_errors.cpp new file mode 100644 index 0000000..4e09796 --- /dev/null +++ b/tests/test_errors.cpp @@ -0,0 +1,141 @@ +#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(); +}