cdemo/tests/test_errors.cpp

100 lines
3.9 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "gtest/gtest.h"
#include "src/errors.cpp"
#include <iostream>
#include <csignal>
#include <csetjmp>
// 全局跳转点,用于捕获信号
static jmp_buf jump_buffer;
// 信号处理函数
void signal_handler(int sig) {
(void)sig; // 抑制未使用参数警告
longjmp(jump_buffer, 1);
}
// 测试夹具类
class ErrorsTest : public ::testing::Test {
protected:
// 保存原始的标准输出流
std::streambuf* original_cout;
// 用于捕获输出的字符串流
std::stringstream captured_cout;
void SetUp() override {
// 重定向 std::cout 到字符串流以捕获输出
original_cout = std::cout.rdbuf();
std::cout.rdbuf(captured_cout.rdbuf());
// 设置信号处理程序
std::signal(SIGSEGV, signal_handler);
std::signal(SIGABRT, signal_handler);
}
void TearDown() override {
// 恢复原始的标准输出流
std::cout.rdbuf(original_cout);
// 恢复默认信号处理
std::signal(SIGSEGV, SIG_DFL);
std::signal(SIGABRT, SIG_DFL);
}
// 辅助函数:安全执行可能崩溃的函数
bool executeWithCrashProtection(void (*func)()) {
if (setjmp(jump_buffer) == 0) {
func();
return false; // 没有崩溃
} else {
return true; // 发生了崩溃(信号被捕获)
}
}
};
// 测试 test_null_pointer 函数
TEST_F(ErrorsTest, test_null_pointer_CausesCrash) {
// 期望函数执行会触发段错误SIGSEGV
bool didCrash = executeWithCrashProtection(test_null_pointer);
EXPECT_TRUE(didCrash) << "Expected test_null_pointer to cause a segmentation fault (crash).";
}
// 测试 test_array_out_of_bounds 函数
TEST_F(ErrorsTest, test_array_out_of_bounds_CausesCrash) {
// 期望函数执行会触发段错误SIGSEGV或中止SIGABRT
bool didCrash = executeWithCrashProtection(test_array_out_of_bounds);
EXPECT_TRUE(didCrash) << "Expected test_array_out_of_bounds to cause a crash due to out-of-bounds access.";
}
// 测试 test_uninitialized_var 函数
// 注意:使用未初始化变量的行为是未定义的,可能不会立即崩溃。
// 测试主要验证函数可以执行(不保证结果),并检查是否有输出。
TEST_F(ErrorsTest, test_uninitialized_var_UndefinedBehavior) {
// 清除之前的捕获内容
captured_cout.str("");
captured_cout.clear();
// 执行函数。由于行为未定义,我们不假设它会崩溃。
// 在某些环境/编译器下,它可能运行并产生输出或什么都不做。
test_uninitialized_var();
// 获取捕获的输出
std::string output = captured_cout.str();
// 断言是不确定的,因为 val 未初始化。
// 我们只能断言它要么输出了 "val > 10",要么没有输出。
// 这是一个演示,实际中很难对未定义行为进行有意义的断言。
// 我们可以检查函数是否至少执行完毕而没有抛出异常(尽管崩溃也是可能的)。
// 更合适的做法可能是记录一个警告,或者使用工具(如 Valgrind, MSAN来检测此类错误。
// 这里我们简单地不添加强断言,仅作为演示。
// 可以检查输出是否为空或者是特定字符串,但这依赖于未定义的值。
// 例如,如果 val 恰好 > 10输出会是 "val > 10\n"。
// 我们只记录输出,不做确定性断言。
std::cout << "Note: test_uninitialized_var executed. Output (if any): '" << output << "'" << std::endl;
// 没有 EXPECT 断言,因为行为未定义。
// 一个替代方案是使用死亡测试,但未初始化读取不保证崩溃。
}
// 主函数(通常由 gtest_main 提供,这里显式写出用于独立编译)
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}