Compare commits
1 Commits
main
...
test_20260
| Author | SHA1 | Date |
|---|---|---|
|
|
ce28f1baf1 |
|
|
@ -0,0 +1,139 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/errors.cpp"
|
||||
#include <iostream>
|
||||
#include <csetjmp>
|
||||
#include <csignal>
|
||||
|
||||
// 全局变量用于信号处理
|
||||
static std::jmp_buf jump_buffer;
|
||||
static volatile sig_atomic_t gSignalStatus = 0;
|
||||
|
||||
// 信号处理函数
|
||||
void signal_handler(int signal) {
|
||||
gSignalStatus = signal;
|
||||
std::longjmp(jump_buffer, 1);
|
||||
}
|
||||
|
||||
// 测试夹具类
|
||||
class ErrorsTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
// 保存旧的信号处理器
|
||||
old_sigsegv_handler = std::signal(SIGSEGV, signal_handler);
|
||||
old_sigabrt_handler = std::signal(SIGABRT, signal_handler);
|
||||
gSignalStatus = 0;
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// 恢复旧的信号处理器
|
||||
std::signal(SIGSEGV, old_sigsegv_handler);
|
||||
std::signal(SIGABRT, old_sigabrt_handler);
|
||||
}
|
||||
|
||||
// 检查是否捕获到预期的信号
|
||||
bool expectSignal(int expected_signal) {
|
||||
if (setjmp(jump_buffer) == 0) {
|
||||
// 第一次进入,执行可能崩溃的代码
|
||||
return false;
|
||||
} else {
|
||||
// 从信号处理器跳转回来
|
||||
return gSignalStatus == expected_signal;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
using SignalHandler = void (*)(int);
|
||||
SignalHandler old_sigsegv_handler;
|
||||
SignalHandler old_sigabrt_handler;
|
||||
};
|
||||
|
||||
// 测试 test_null_pointer 函数
|
||||
TEST_F(ErrorsTest, TestNullPointerTriggersSegmentationFault) {
|
||||
// 这个测试期望函数触发段错误(SIGSEGV)
|
||||
// 由于我们设置了信号处理器,测试不会崩溃
|
||||
bool caught_signal = expectSignal(SIGSEGV);
|
||||
if (!caught_signal) {
|
||||
// 如果没有通过信号捕获,直接调用函数(这会导致测试进程崩溃)
|
||||
// 但在我们的测试夹具中,这应该被信号处理器捕获
|
||||
test_null_pointer();
|
||||
}
|
||||
// 验证我们捕获到了段错误信号
|
||||
EXPECT_TRUE(caught_signal) << "Expected SIGSEGV signal from null pointer dereference";
|
||||
}
|
||||
|
||||
TEST_F(ErrorsTest, TestNullPointerUndefinedBehavior) {
|
||||
// 这个测试验证空指针解引用是未定义行为
|
||||
// 在某些平台上,可能不会立即崩溃,但行为是未定义的
|
||||
// 我们主要验证函数可以编译和链接
|
||||
SUCCEED() << "test_null_pointer function exists and can be called";
|
||||
}
|
||||
|
||||
// 测试 test_array_out_of_bounds 函数
|
||||
TEST_F(ErrorsTest, TestArrayOutOfBoundsTriggersMemoryError) {
|
||||
// 数组越界访问可能触发段错误(SIGSEGV)或其他内存错误
|
||||
bool caught_signal = expectSignal(SIGSEGV);
|
||||
if (!caught_signal) {
|
||||
test_array_out_of_bounds();
|
||||
}
|
||||
// 数组越界是未定义行为,可能不会立即崩溃
|
||||
// 但我们期望在大多数实现中会触发内存错误
|
||||
if (caught_signal) {
|
||||
EXPECT_TRUE(caught_signal) << "Expected memory error from array out of bounds access";
|
||||
} else {
|
||||
// 如果没有崩溃,记录警告
|
||||
ADD_FAILURE() << "Array out of bounds access did not trigger immediate crash (undefined behavior)";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ErrorsTest, TestArrayOutOfBoundsUndefinedBehavior) {
|
||||
// 验证数组越界访问是未定义行为
|
||||
// 测试函数的存在性和可调用性
|
||||
SUCCEED() << "test_array_out_of_bounds function exists and can be called";
|
||||
}
|
||||
|
||||
// 测试 test_uninitialized_var 函数
|
||||
TEST_F(ErrorsTest, TestUninitializedVarUndefinedBehavior) {
|
||||
// 使用未初始化变量是未定义行为
|
||||
// 这个测试主要验证函数可以编译和运行
|
||||
// 由于行为未定义,我们无法预测具体输出
|
||||
|
||||
// 重定向std::cout以捕获输出
|
||||
testing::internal::CaptureStdout();
|
||||
|
||||
// 调用函数 - 行为未定义,可能输出任何内容或不输出
|
||||
test_uninitialized_var();
|
||||
|
||||
std::string output = testing::internal::GetCapturedStdout();
|
||||
|
||||
// 由于val未初始化,其值不确定,因此输出也不确定
|
||||
// 我们只验证函数执行没有崩溃
|
||||
SUCCEED() << "test_uninitialized_var executed without crash (output: '" << output << "')";
|
||||
}
|
||||
|
||||
TEST_F(ErrorsTest, TestUninitializedVarRandomBehavior) {
|
||||
// 多次调用函数,观察未初始化变量的随机行为
|
||||
// 注意:这仍然是未定义行为,不仅仅是随机
|
||||
|
||||
std::set<std::string> outputs;
|
||||
const int num_runs = 10;
|
||||
|
||||
for (int i = 0; i < num_runs; ++i) {
|
||||
testing::internal::CaptureStdout();
|
||||
test_uninitialized_var();
|
||||
std::string output = testing::internal::GetCapturedStdout();
|
||||
outputs.insert(output);
|
||||
}
|
||||
|
||||
// 未初始化变量可能导致不同输出或相同输出
|
||||
// 我们只记录观察到的行为
|
||||
std::cout << "Observed " << outputs.size() << " different outputs from "
|
||||
<< num_runs << " runs of test_uninitialized_var" << std::endl;
|
||||
|
||||
SUCCEED() << "test_uninitialized_var shows undefined behavior across multiple runs";
|
||||
}
|
||||
|
||||
// 主函数
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
Loading…
Reference in New Issue