Compare commits
1 Commits
main
...
test_20260
| Author | SHA1 | Date |
|---|---|---|
|
|
a3e1425ac2 |
|
|
@ -0,0 +1,141 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/errors.cpp"
|
||||
#include <iostream>
|
||||
#include <csignal>
|
||||
#include <csetjmp>
|
||||
|
||||
// 信号处理跳转缓冲区,用于捕获崩溃
|
||||
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();
|
||||
}
|
||||
Loading…
Reference in New Issue