cdemo/tests/test_errors.cpp

91 lines
3.4 KiB
C++
Raw Permalink Normal View History

2026-04-14 03:15:04 +00:00
#include "gtest/gtest.h"
#include "src/errors.cpp"
#include <iostream>
#include <csetjmp>
#include <csignal>
// 全局跳转点,用于处理信号
static std::jmp_buf jump_buffer;
// 信号处理函数
static void signal_handler(int sig) {
std::longjmp(jump_buffer, 1);
}
// 测试夹具类
class ErrorsTest : public ::testing::Test {
protected:
// 保存旧的信号处理器
struct sigaction old_action{};
struct sigaction new_action{};
void SetUp() override {
// 设置 SIGSEGV 和 SIGABRT 的信号处理器
new_action.sa_handler = signal_handler;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGSEGV, &new_action, &old_action);
sigaction(SIGABRT, &new_action, nullptr);
}
void TearDown() override {
// 恢复旧的信号处理器
sigaction(SIGSEGV, &old_action, nullptr);
}
};
// 测试 test_null_pointer 函数
// 该函数会解引用空指针,预期会触发段错误 (SIGSEGV) 或程序终止
TEST_F(ErrorsTest, test_null_pointer_TriggersCrash) {
// 设置跳转点,如果发生信号则跳转回来
if (setjmp(jump_buffer) == 0) {
// 尝试调用会崩溃的函数
test_null_pointer();
// 如果执行到这里,说明没有崩溃,测试失败
FAIL() << "Expected test_null_pointer to cause a crash (SIGSEGV), but it didn't.";
} else {
// 成功捕获到信号,测试通过
SUCCEED();
}
}
// 测试 test_array_out_of_bounds 函数
// 该函数会访问数组越界,预期会触发段错误 (SIGSEGV) 或程序终止
TEST_F(ErrorsTest, test_array_out_of_bounds_TriggersCrash) {
if (setjmp(jump_buffer) == 0) {
test_array_out_of_bounds();
FAIL() << "Expected test_array_out_of_bounds to cause a crash (SIGSEGV), but it didn't.";
} else {
SUCCEED();
}
}
// 测试 test_uninitialized_var 函数
// 该函数使用未初始化的变量,行为是未定义的。
// 我们无法可靠地测试其输出,但可以验证函数能运行而不崩溃(尽管结果不可预测)。
// 注意:这是一个“正常”路径测试,因为函数定义本身没有语法错误,可以执行。
TEST_F(ErrorsTest, test_uninitialized_var_RunsWithoutCrash) {
// 由于使用未初始化变量是未定义行为,它可能崩溃也可能不崩溃。
// 我们只测试函数可以被调用而不导致必然的、可捕获的崩溃如SIGSEGV
// 我们使用一个 try-catch 块但C++标准异常通常捕获不了内存错误。
// 因此,我们设置一个信号处理器,如果它因未初始化变量而意外崩溃,我们也能捕获。
if (setjmp(jump_buffer) == 0) {
test_uninitialized_var();
// 如果执行到这里说明没有触发我们设置的信号处理器SIGSEGV/SIGABRT
// 这被认为是测试通过,因为函数执行完成了。
// 我们无法断言它的输出,因为 val 是未定义的。
SUCCEED();
} else {
// 如果它意外地因为未初始化变量而崩溃了,我们也记录下来。
// 这在某些平台/编译器上是有可能的。
ADD_FAILURE() << "test_uninitialized_var caused a signal. This is possible UB.";
}
}
// 主函数
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}