121 lines
3.8 KiB
C++
121 lines
3.8 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);
|
|
}
|
|
|
|
// 测试夹具类
|
|
class ErrorsTest : public ::testing::Test {
|
|
protected:
|
|
// 保存原始信号处理器
|
|
void (*original_sigsegv_handler)(int);
|
|
void (*original_sigabrt_handler)(int);
|
|
|
|
void SetUp() override {
|
|
// 安装自定义信号处理器
|
|
original_sigsegv_handler = signal(SIGSEGV, signal_handler);
|
|
original_sigabrt_handler = signal(SIGABRT, signal_handler);
|
|
}
|
|
|
|
void TearDown() override {
|
|
// 恢复原始信号处理器
|
|
signal(SIGSEGV, original_sigsegv_handler);
|
|
signal(SIGABRT, original_sigabrt_handler);
|
|
}
|
|
};
|
|
|
|
// 测试 test_null_pointer 函数
|
|
TEST_F(ErrorsTest, TestNullPointerTriggersSignal) {
|
|
// 设置跳转点,如果发生信号则跳转回此处
|
|
if (setjmp(jump_buffer) == 0) {
|
|
// 尝试执行会触发信号的代码
|
|
test_null_pointer();
|
|
// 如果执行到这里,说明没有触发信号,测试失败
|
|
FAIL() << "Expected test_null_pointer to trigger a signal but it didn't";
|
|
} else {
|
|
// 成功捕获到信号
|
|
SUCCEED();
|
|
}
|
|
}
|
|
|
|
// 测试 test_array_out_of_bounds 函数
|
|
TEST_F(ErrorsTest, TestArrayOutOfBoundsTriggersSignal) {
|
|
if (setjmp(jump_buffer) == 0) {
|
|
test_array_out_of_bounds();
|
|
FAIL() << "Expected test_array_out_of_bounds to trigger a signal but it didn't";
|
|
} else {
|
|
SUCCEED();
|
|
}
|
|
}
|
|
|
|
// 测试 test_uninitialized_var 函数
|
|
// 注意:使用未初始化变量不一定会触发信号,行为是未定义的
|
|
// 我们只能验证函数可以执行而不崩溃(在某些平台上)
|
|
TEST_F(ErrorsTest, TestUninitializedVarDoesNotCrash) {
|
|
// 这个测试可能通过,也可能失败,取决于编译器和运行时环境
|
|
// 我们主要验证函数可以调用而不导致程序终止
|
|
EXPECT_NO_FATAL_FAILURE(test_uninitialized_var());
|
|
}
|
|
|
|
// 边界条件测试:验证正常数组访问不会触发信号
|
|
TEST_F(ErrorsTest, TestNormalArrayAccess) {
|
|
// 创建一个简单的测试来验证正常数组访问
|
|
int arr[3] = {1, 2, 3};
|
|
|
|
if (setjmp(jump_buffer) == 0) {
|
|
// 正常访问数组元素
|
|
std::cout << "Normal array access: " << arr[0] << std::endl;
|
|
std::cout << "Normal array access: " << arr[1] << std::endl;
|
|
std::cout << "Normal array access: " << arr[2] << std::endl;
|
|
SUCCEED();
|
|
} else {
|
|
FAIL() << "Normal array access triggered a signal unexpectedly";
|
|
}
|
|
}
|
|
|
|
// 特殊场景:验证空指针检查
|
|
TEST_F(ErrorsTest, TestNullPointerCheck) {
|
|
int* p = nullptr;
|
|
|
|
if (setjmp(jump_buffer) == 0) {
|
|
// 尝试解引用空指针
|
|
*p = 10;
|
|
FAIL() << "Expected null pointer dereference to trigger a signal but it didn't";
|
|
} else {
|
|
SUCCEED();
|
|
}
|
|
}
|
|
|
|
// 特殊场景:验证数组边界检查
|
|
TEST_F(ErrorsTest, TestArrayBoundaryCheck) {
|
|
int arr[3] = {1, 2, 3};
|
|
|
|
if (setjmp(jump_buffer) == 0) {
|
|
// 尝试访问刚好越界的元素(在某些系统上可能不会立即崩溃)
|
|
volatile int value = arr[3]; // 刚好越界
|
|
// 如果执行到这里,测试可能通过,也可能失败
|
|
// 这取决于编译器和运行时环境
|
|
std::cout << "Array access at index 3 returned: " << value << std::endl;
|
|
// 我们不标记为失败,因为行为是未定义的
|
|
SUCCEED();
|
|
} else {
|
|
// 成功捕获到信号
|
|
SUCCEED();
|
|
}
|
|
}
|
|
|
|
// 主函数
|
|
int main(int argc, char **argv) {
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|