133 lines
4.4 KiB
C++
133 lines
4.4 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 signum) {
|
|
longjmp(jump_buffer, 1);
|
|
}
|
|
|
|
// 测试夹具类
|
|
class ErrorsTest : public ::testing::Test {
|
|
protected:
|
|
// 保存原始信号处理器
|
|
void (*original_signal_handler)(int);
|
|
|
|
void SetUp() override {
|
|
// 设置自定义信号处理器来捕获段错误
|
|
original_signal_handler = signal(SIGSEGV, signal_handler);
|
|
}
|
|
|
|
void TearDown() override {
|
|
// 恢复原始信号处理器
|
|
signal(SIGSEGV, original_signal_handler);
|
|
}
|
|
};
|
|
|
|
// 测试 test_null_pointer 函数
|
|
TEST_F(ErrorsTest, test_null_pointer_should_crash) {
|
|
// 使用 setjmp/longjmp 来捕获预期的崩溃
|
|
if (setjmp(jump_buffer) == 0) {
|
|
// 这应该触发段错误
|
|
test_null_pointer();
|
|
// 如果执行到这里,说明没有崩溃,测试失败
|
|
FAIL() << "Expected test_null_pointer to crash due to null pointer dereference";
|
|
} else {
|
|
// 成功捕获到信号,测试通过
|
|
SUCCEED();
|
|
}
|
|
}
|
|
|
|
// 测试 test_array_out_of_bounds 函数
|
|
TEST_F(ErrorsTest, test_array_out_of_bounds_should_crash) {
|
|
// 使用 setjmp/longjmp 来捕获预期的崩溃
|
|
if (setjmp(jump_buffer) == 0) {
|
|
// 这应该触发段错误或未定义行为
|
|
test_array_out_of_bounds();
|
|
// 如果执行到这里,说明没有崩溃,测试失败
|
|
FAIL() << "Expected test_array_out_of_bounds to crash due to array out of bounds";
|
|
} else {
|
|
// 成功捕获到信号,测试通过
|
|
SUCCEED();
|
|
}
|
|
}
|
|
|
|
// 测试 test_uninitialized_var 函数
|
|
TEST_F(ErrorsTest, test_uninitialized_var_has_undefined_behavior) {
|
|
// 未初始化变量的行为是未定义的,可能不会崩溃
|
|
// 我们只能验证函数可以执行而不崩溃(或者可能崩溃)
|
|
// 由于行为未定义,我们主要测试函数能够被调用
|
|
|
|
// 注意:未初始化变量的行为是未定义的,可能不会立即导致崩溃
|
|
// 但可能导致不可预测的结果
|
|
|
|
// 我们可以多次调用该函数,观察是否有时会崩溃
|
|
bool crashed_at_least_once = false;
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
if (setjmp(jump_buffer) == 0) {
|
|
test_uninitialized_var();
|
|
// 没有崩溃,继续下一次迭代
|
|
} else {
|
|
// 发生了崩溃
|
|
crashed_at_least_once = true;
|
|
// 重置跳转缓冲区以进行下一次迭代
|
|
signal(SIGSEGV, signal_handler);
|
|
}
|
|
}
|
|
|
|
// 由于未初始化变量的行为是未定义的,我们无法做出确定的断言
|
|
// 但我们可以记录观察到的行为
|
|
if (crashed_at_least_once) {
|
|
std::cout << "Note: test_uninitialized_var caused a crash in at least one iteration" << std::endl;
|
|
} else {
|
|
std::cout << "Note: test_uninitialized_var did not cause a crash in any iteration" << std::endl;
|
|
}
|
|
|
|
// 对于未定义行为,我们无法做出确定的断言
|
|
// 但测试至少验证了函数可以被调用
|
|
SUCCEED();
|
|
}
|
|
|
|
// 边界条件测试:验证这些错误函数确实会导致问题
|
|
TEST_F(ErrorsTest, verify_error_functions_are_dangerous) {
|
|
// 这个测试验证所有三个函数都存在潜在的危险行为
|
|
// 通过尝试执行它们并观察是否发生崩溃
|
|
|
|
int dangerous_functions = 3;
|
|
int detected_danger = 0;
|
|
|
|
// 测试 test_null_pointer
|
|
if (setjmp(jump_buffer) == 0) {
|
|
test_null_pointer();
|
|
} else {
|
|
detected_danger++;
|
|
signal(SIGSEGV, signal_handler);
|
|
}
|
|
|
|
// 测试 test_array_out_of_bounds
|
|
if (setjmp(jump_buffer) == 0) {
|
|
test_array_out_of_bounds();
|
|
} else {
|
|
detected_danger++;
|
|
signal(SIGSEGV, signal_handler);
|
|
}
|
|
|
|
// 测试 test_uninitialized_var (可能不会崩溃,但行为未定义)
|
|
// 我们调用它但不检查崩溃,因为未初始化变量的行为是未定义的
|
|
test_uninitialized_var();
|
|
|
|
// 至少前两个函数应该被检测为危险的
|
|
EXPECT_GE(detected_danger, 2) << "At least two of the error functions should be detected as dangerous";
|
|
}
|
|
|
|
// 主函数
|
|
int main(int argc, char **argv) {
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
} |