113 lines
3.3 KiB
C++
113 lines
3.3 KiB
C++
|
|
#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, TestNullPointer) {
|
||
|
|
// 设置信号处理程序以捕获段错误
|
||
|
|
struct sigaction sa;
|
||
|
|
struct sigaction old_sa;
|
||
|
|
|
||
|
|
sa.sa_handler = signal_handler;
|
||
|
|
sigemptyset(&sa.sa_mask);
|
||
|
|
sa.sa_flags = 0;
|
||
|
|
|
||
|
|
// 保存旧的信号处理程序
|
||
|
|
sigaction(SIGSEGV, &sa, &old_sa);
|
||
|
|
|
||
|
|
// 设置跳转点
|
||
|
|
if (setjmp(jump_buffer) == 0) {
|
||
|
|
// 尝试调用会触发段错误的函数
|
||
|
|
test_null_pointer();
|
||
|
|
// 如果执行到这里,说明没有触发段错误
|
||
|
|
FAIL() << "Expected segmentation fault but none occurred";
|
||
|
|
} else {
|
||
|
|
// 成功捕获到段错误
|
||
|
|
SUCCEED();
|
||
|
|
}
|
||
|
|
|
||
|
|
// 恢复旧的信号处理程序
|
||
|
|
sigaction(SIGSEGV, &old_sa, nullptr);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 测试数组越界访问
|
||
|
|
TEST(ErrorsTest, TestArrayOutOfBounds) {
|
||
|
|
// 设置信号处理程序以捕获段错误
|
||
|
|
struct sigaction sa;
|
||
|
|
struct sigaction old_sa;
|
||
|
|
|
||
|
|
sa.sa_handler = signal_handler;
|
||
|
|
sigemptyset(&sa.sa_mask);
|
||
|
|
sa.sa_flags = 0;
|
||
|
|
|
||
|
|
// 保存旧的信号处理程序
|
||
|
|
sigaction(SIGSEGV, &sa, &old_sa);
|
||
|
|
|
||
|
|
// 设置跳转点
|
||
|
|
if (setjmp(jump_buffer) == 0) {
|
||
|
|
// 尝试调用会触发段错误的函数
|
||
|
|
test_array_out_of_bounds();
|
||
|
|
// 如果执行到这里,说明没有触发段错误
|
||
|
|
FAIL() << "Expected segmentation fault but none occurred";
|
||
|
|
} else {
|
||
|
|
// 成功捕获到段错误
|
||
|
|
SUCCEED();
|
||
|
|
}
|
||
|
|
|
||
|
|
// 恢复旧的信号处理程序
|
||
|
|
sigaction(SIGSEGV, &old_sa, nullptr);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 测试未初始化变量使用
|
||
|
|
TEST(ErrorsTest, TestUninitializedVar) {
|
||
|
|
// 未初始化变量的行为是未定义的,可能不会立即崩溃
|
||
|
|
// 我们只能验证函数可以执行而不崩溃
|
||
|
|
// 多次运行以增加检测到问题的机会
|
||
|
|
for (int i = 0; i < 100; ++i) {
|
||
|
|
// 设置信号处理程序以捕获可能的段错误
|
||
|
|
struct sigaction sa;
|
||
|
|
struct sigaction old_sa;
|
||
|
|
|
||
|
|
sa.sa_handler = signal_handler;
|
||
|
|
sigemptyset(&sa.sa_mask);
|
||
|
|
sa.sa_flags = 0;
|
||
|
|
|
||
|
|
// 保存旧的信号处理程序
|
||
|
|
sigaction(SIGSEGV, &sa, &old_sa);
|
||
|
|
|
||
|
|
// 设置跳转点
|
||
|
|
if (setjmp(jump_buffer) == 0) {
|
||
|
|
// 尝试调用函数
|
||
|
|
test_uninitialized_var();
|
||
|
|
// 如果执行到这里,说明没有触发段错误
|
||
|
|
// 这是可接受的,因为未初始化变量的行为是未定义的
|
||
|
|
} else {
|
||
|
|
// 如果捕获到段错误,记录但继续测试
|
||
|
|
ADD_FAILURE() << "Segmentation fault occurred at iteration " << i;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 恢复旧的信号处理程序
|
||
|
|
sigaction(SIGSEGV, &old_sa, nullptr);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 由于未初始化变量的行为是未定义的,我们无法做出确定的断言
|
||
|
|
// 测试通过意味着函数可以执行而不一定意味着行为正确
|
||
|
|
SUCCEED();
|
||
|
|
}
|
||
|
|
|
||
|
|
// 主函数
|
||
|
|
int main(int argc, char **argv) {
|
||
|
|
::testing::InitGoogleTest(&argc, argv);
|
||
|
|
return RUN_ALL_TESTS();
|
||
|
|
}
|