cdemo/tests/test_errors.cpp

89 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 <gmock/gmock.h>
#include <iostream>
#include <sstream>
#include <csignal>
// 由于被测函数包含未定义行为(空指针解引用、数组越界、未初始化变量),
// 这些函数在正常执行时会导致程序崩溃或不可预测的结果。
// 因此,测试用例的设计侧重于验证这些函数在特定条件下的行为,
// 例如通过信号处理或模拟环境来捕获崩溃,或者验证函数不会在非崩溃路径上产生意外输出。
// 注意:直接调用这些函数会导致测试程序崩溃,因此测试用例使用子进程或信号处理来隔离。
// 辅助函数:捕获信号并验证
void signal_handler(int sig) {
// 空实现,仅用于捕获信号
}
// 测试 test_null_pointer 函数
// 由于该函数会解引用空指针,预期会导致 SIGSEGV 信号
TEST(ErrorTest, NullPointerCausesSegfault) {
// 设置信号处理函数
signal(SIGSEGV, signal_handler);
// 使用 EXPECT_EXIT 宏来验证程序因 SIGSEGV 而退出
// 注意:由于函数直接崩溃,无法正常返回,因此使用 EXPECT_EXIT
EXPECT_EXIT({
test_null_pointer();
}, ::testing::KilledBySignal(SIGSEGV), "");
}
// 测试 test_array_out_of_bounds 函数
// 数组越界访问是未定义行为,可能不会立即崩溃,但通常会导致访问非法内存
// 这里我们使用 EXPECT_EXIT 来捕获可能的 SIGSEGV但并非所有实现都会崩溃
// 因此,我们也可以验证函数不会产生意外输出(如果未崩溃)
TEST(ErrorTest, ArrayOutOfBoundsUndefinedBehavior) {
// 由于未定义行为,测试可能不稳定。这里我们尝试捕获 SIGSEGV
// 如果程序崩溃,测试通过;如果不崩溃,我们至少验证没有异常输出
// 但更合理的做法是使用 EXPECT_EXIT 并允许 SIGSEGV
EXPECT_EXIT({
test_array_out_of_bounds();
}, ::testing::KilledBySignal(SIGSEGV), "");
}
// 测试 test_uninitialized_var 函数
// 未初始化变量的使用也是未定义行为,可能不会立即崩溃
// 我们使用 EXPECT_EXIT 来捕获可能的 SIGSEGV但通常不会崩溃
// 因此,我们也可以验证函数不会产生意外输出
TEST(ErrorTest, UninitializedVarUndefinedBehavior) {
// 未初始化变量通常不会导致崩溃,但行为不可预测
// 这里我们尝试捕获 SIGSEGV但预期不会发生
// 更合理的测试是验证函数不会产生异常输出
testing::internal::CaptureStdout();
test_uninitialized_var();
std::string output = testing::internal::GetCapturedStdout();
// 由于 val 未初始化,条件可能为真或假,输出可能为空或包含 "val > 10"
// 我们只验证没有异常发生(即函数正常返回)
EXPECT_TRUE(true); // 函数正常返回即视为通过
}
// 额外的测试:验证函数在非崩溃路径下的行为
// 由于这些函数设计为演示错误,我们也可以测试它们是否按预期产生输出
// 但注意:直接调用会导致崩溃,因此需要特殊处理
// 使用子进程测试 test_null_pointer
TEST(ErrorTest, NullPointerSubprocess) {
// 使用 EXPECT_EXIT 验证子进程因 SIGSEGV 退出
EXPECT_EXIT({
test_null_pointer();
}, ::testing::KilledBySignal(SIGSEGV), "");
}
// 使用子进程测试 test_array_out_of_bounds
TEST(ErrorTest, ArrayOutOfBoundsSubprocess) {
// 使用 EXPECT_EXIT 验证子进程可能因 SIGSEGV 退出
EXPECT_EXIT({
test_array_out_of_bounds();
}, ::testing::KilledBySignal(SIGSEGV), "");
}
// 使用子进程测试 test_uninitialized_var
TEST(ErrorTest, UninitializedVarSubprocess) {
// 未初始化变量通常不会导致崩溃,但行为不可预测
// 我们只验证子进程正常退出返回0
EXPECT_EXIT({
test_uninitialized_var();
exit(0);
}, ::testing::ExitedWithCode(0), "");
}