Compare commits
1 Commits
main
...
test_20260
| Author | SHA1 | Date |
|---|---|---|
|
|
b2146f26db |
|
|
@ -0,0 +1,105 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/errors.cpp"
|
||||
#include <iostream>
|
||||
#include <csignal>
|
||||
#include <csetjmp>
|
||||
|
||||
// 用于捕获信号和异常的全局变量
|
||||
static std::jmp_buf jump_buffer;
|
||||
static volatile std::sig_atomic_t gSignalStatus;
|
||||
|
||||
// 信号处理函数
|
||||
void signal_handler(int signal) {
|
||||
gSignalStatus = signal;
|
||||
std::longjmp(jump_buffer, 1);
|
||||
}
|
||||
|
||||
namespace {
|
||||
// 测试类,用于设置和恢复信号处理器
|
||||
class SignalGuard {
|
||||
public:
|
||||
SignalGuard(int sig, void (*handler)(int)) : m_sig(sig), m_old_handler(std::signal(sig, handler)) {}
|
||||
~SignalGuard() { std::signal(m_sig, m_old_handler); }
|
||||
private:
|
||||
int m_sig;
|
||||
void (*m_old_handler)(int);
|
||||
};
|
||||
|
||||
// 测试 test_null_pointer 函数
|
||||
TEST(ErrorsTest, TestNullPointerTriggersSignal) {
|
||||
// 安装 SIGSEGV 信号处理器
|
||||
SignalGuard guard(SIGSEGV, signal_handler);
|
||||
gSignalStatus = 0;
|
||||
|
||||
// 使用 setjmp/longjmp 来捕获信号后的跳转
|
||||
if (setjmp(jump_buffer) == 0) {
|
||||
// 尝试执行会触发段错误的函数
|
||||
test_null_pointer();
|
||||
// 如果执行到这里,说明没有触发信号,测试失败
|
||||
FAIL() << "Expected test_null_pointer to cause a segmentation fault";
|
||||
} else {
|
||||
// 成功捕获到信号
|
||||
EXPECT_EQ(gSignalStatus, SIGSEGV);
|
||||
}
|
||||
}
|
||||
|
||||
// 测试 test_array_out_of_bounds 函数
|
||||
TEST(ErrorsTest, TestArrayOutOfBoundsTriggersSignal) {
|
||||
// 安装 SIGSEGV 信号处理器
|
||||
SignalGuard guard(SIGSEGV, signal_handler);
|
||||
gSignalStatus = 0;
|
||||
|
||||
if (setjmp(jump_buffer) == 0) {
|
||||
test_array_out_of_bounds();
|
||||
FAIL() << "Expected test_array_out_of_bounds to cause a segmentation fault";
|
||||
} else {
|
||||
EXPECT_EQ(gSignalStatus, SIGSEGV);
|
||||
}
|
||||
}
|
||||
|
||||
// 测试 test_uninitialized_var 函数
|
||||
// 注意:未初始化变量的行为是未定义的,可能不会崩溃,但结果不可预测。
|
||||
// 我们无法可靠地测试其具体行为,但可以验证函数调用本身不会导致程序终止(如信号)。
|
||||
// 然而,为了演示,我们仍然运行它,但不对其输出做任何断言,因为它是未定义的。
|
||||
TEST(ErrorsTest, TestUninitializedVarRunsWithoutCrash) {
|
||||
// 这个测试主要是为了确保函数可以被调用,而不导致程序崩溃(尽管行为未定义)。
|
||||
// 由于未初始化变量的值是未定义的,我们无法断言其具体行为。
|
||||
// 在某些配置下(如调试模式),变量可能被初始化为0,但这不是保证的。
|
||||
// 因此,我们只调用函数,不进行断言。
|
||||
// 注意:这实际上不是一个好的单元测试,因为它没有验证任何确定的行为。
|
||||
// 它只是为了演示如何“测试”一个具有未定义行为的函数。
|
||||
// 在实际项目中,这样的函数应该被修复,而不是被测试。
|
||||
test_uninitialized_var();
|
||||
// 如果程序执行到这里,说明没有崩溃,测试通过。
|
||||
// 我们无法对输出做任何有意义的断言。
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
// 额外的测试:验证正常数组访问不会崩溃(作为对比)
|
||||
TEST(ErrorsTest, TestNormalArrayAccessDoesNotCrash) {
|
||||
int arr[3] = {1, 2, 3};
|
||||
EXPECT_EQ(arr[0], 1);
|
||||
EXPECT_EQ(arr[1], 2);
|
||||
EXPECT_EQ(arr[2], 3);
|
||||
// 访问有效索引,不应崩溃
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
// 额外的测试:验证已初始化的指针解引用不会崩溃(作为对比)
|
||||
TEST(ErrorsTest, TestValidPointerDereferenceDoesNotCrash) {
|
||||
int value = 42;
|
||||
int* p = &value;
|
||||
EXPECT_EQ(*p, 42);
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
// 额外的测试:验证已初始化的变量行为可预测
|
||||
TEST(ErrorsTest, TestInitializedVarBehaviorIsPredictable) {
|
||||
int val = 15; // 明确初始化
|
||||
if (val > 10) {
|
||||
SUCCEED(); // 条件为真,符合预期
|
||||
} else {
|
||||
FAIL() << "Initialized variable should behave predictably";
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue