133 lines
3.8 KiB
C++
133 lines
3.8 KiB
C++
#include "gtest/gtest.h"
|
||
#include "src/errors.cpp"
|
||
#include <iostream>
|
||
#include <signal.h>
|
||
#include <setjmp.h>
|
||
|
||
// 用于捕获信号的跳转缓冲区
|
||
static jmp_buf env;
|
||
|
||
// 信号处理函数
|
||
void signal_handler(int sig) {
|
||
(void)sig;
|
||
longjmp(env, 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);
|
||
|
||
// 使用setjmp/longjmp来捕获段错误
|
||
if (setjmp(env) == 0) {
|
||
// 尝试调用会触发段错误的函数
|
||
test_null_pointer();
|
||
// 如果执行到这里,说明没有触发段错误,测试失败
|
||
FAIL() << "Expected segmentation fault from null pointer dereference";
|
||
} else {
|
||
// 成功捕获到段错误,测试通过
|
||
SUCCEED();
|
||
}
|
||
|
||
// 恢复旧的信号处理器
|
||
sigaction(SIGSEGV, &old_sa, NULL);
|
||
}
|
||
|
||
// 测试数组越界访问
|
||
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);
|
||
|
||
// 使用setjmp/longjmp来捕获段错误
|
||
if (setjmp(env) == 0) {
|
||
// 尝试调用会触发段错误的函数
|
||
test_array_out_of_bounds();
|
||
// 如果执行到这里,说明没有触发段错误,测试失败
|
||
FAIL() << "Expected segmentation fault from array out of bounds access";
|
||
} else {
|
||
// 成功捕获到段错误,测试通过
|
||
SUCCEED();
|
||
}
|
||
|
||
// 恢复旧的信号处理器
|
||
sigaction(SIGSEGV, &old_sa, NULL);
|
||
}
|
||
|
||
// 测试未初始化变量使用
|
||
TEST(ErrorsTest, TestUninitializedVar) {
|
||
// 未初始化变量的行为是未定义的,可能不会立即崩溃
|
||
// 我们只能验证函数可以执行而不崩溃(尽管行为未定义)
|
||
EXPECT_NO_FATAL_FAILURE(test_uninitialized_var());
|
||
|
||
// 注意:由于未初始化变量的值是未定义的,我们无法预测具体的输出
|
||
// 这个测试只是确保函数不会导致程序崩溃
|
||
// 在实际测试中,可能需要多次运行来观察不同的行为
|
||
}
|
||
|
||
// 边界条件测试:测试数组边界值
|
||
TEST(ErrorsTest, TestArrayBoundaryConditions) {
|
||
// 演示正确的数组访问
|
||
int arr[3] = {1, 2, 3};
|
||
|
||
// 测试合法边界
|
||
EXPECT_EQ(arr[0], 1);
|
||
EXPECT_EQ(arr[2], 3);
|
||
|
||
// 注意:arr[3] 是越界的,即使编译器可能允许
|
||
// 但这是未定义行为
|
||
}
|
||
|
||
// 特殊场景测试:测试指针初始化为非空值
|
||
TEST(ErrorsTest, TestValidPointerDereference) {
|
||
int value = 42;
|
||
int* p = &value;
|
||
|
||
// 合法的指针解引用
|
||
EXPECT_EQ(*p, 42);
|
||
|
||
// 修改值
|
||
*p = 100;
|
||
EXPECT_EQ(value, 100);
|
||
}
|
||
|
||
// 测试未初始化变量的不同场景
|
||
TEST(ErrorsTest, TestUninitializedVarScenarios) {
|
||
// 场景1:局部未初始化变量
|
||
{
|
||
int val;
|
||
// 行为未定义,但我们可以测试它是否可以被读取(尽管值不确定)
|
||
volatile int read_val = val; // 使用volatile防止优化
|
||
(void)read_val; // 避免未使用变量警告
|
||
}
|
||
|
||
// 场景2:静态未初始化变量(会被初始化为0)
|
||
static int static_val;
|
||
EXPECT_EQ(static_val, 0); // 静态变量会被初始化为0
|
||
|
||
// 场景3:正确初始化的变量作为对比
|
||
int initialized_val = 50;
|
||
EXPECT_EQ(initialized_val, 50);
|
||
}
|
||
|
||
// 主函数
|
||
int main(int argc, char **argv) {
|
||
::testing::InitGoogleTest(&argc, argv);
|
||
return RUN_ALL_TESTS();
|
||
}
|