#include "gtest/gtest.h" #include "src/errors.cpp" #include #include #include // 全局变量用于信号处理 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 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(); }