cdemo/tests/test_main.cpp

102 lines
5.1 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 "test_errors.h"
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
// 测试主函数 main
TEST(MainTest, MainExecutesAllErrorFunctions) {
// 由于 main 函数调用了一系列会触发错误或副作用的函数,
// 直接测试其返回值可能不够。
// 策略:通过检查标准输出/错误或程序退出码来验证函数被调用。
// 注意:这依赖于 test_errors.h 中函数的实现(例如,它们可能打印信息)。
// 假设这些函数在出错时会打印特定信息到 stderr 或导致非零退出码(如果被包装)。
// 更健壮的方法是使用死亡测试death test来验证程序是否因特定错误而终止。
// 这里我们演示两种方法:
// 方法1直接调用 main 并检查其返回值如果函数设计为返回0
// 由于 main 函数总是返回 0这个测试价值有限但可以验证链接和基本执行。
// 为了隔离测试,我们通常不直接测试 main而是测试其调用的函数。
// 因此,这个测试用例主要作为集成测试的占位符。
// 在实际项目中main 函数的逻辑应尽可能简单,将测试重点放在其调用的函数上。
// 方法2使用死亡测试验证某些错误函数会导致程序终止例如空指针解引用
// 注意:这需要 test_errors.h 中的函数确实会导致程序崩溃(如 test_null_pointer
// 假设 test_null_pointer() 会解引用空指针导致段错误。
// 使用 ASSERT_DEATH 来验证。
// 注意:死亡测试在某些环境(如 Windows 或某些 sanitizers下可能不可靠。
// 这里我们注释掉,因为 test_errors.h 的实现未知,可能被修改为不崩溃。
/*
ASSERT_DEATH({
test_null_pointer();
}, ".*"); // 匹配任何错误输出
*/
// 由于上述不确定性,我们采用一个更安全的测试:
// 验证 main 函数可以正常编译、链接并执行到返回,没有抛出异常。
// 这通过调用 main 函数并检查其返回值应为0来实现。
// 注意:直接调用 main 函数在 C++ 标准中通常是允许的,但有些编译器可能警告。
// 我们使用 extern "C" 来避免名称修饰问题(如果 main 是 C++函数)。
// 实际上main 函数是全局函数,可以直接调用。
testing::internal::CaptureStdout(); // 捕获 stdout 以避免测试输出干扰
testing::internal::CaptureStderr(); // 捕获 stderr
int result = main(); // 调用 main 函数
std::string output = testing::internal::GetCapturedStdout();
std::string errors = testing::internal::GetCapturedStderr();
// 断言 main 返回 0
EXPECT_EQ(result, 0);
// 可选:断言没有标准错误输出(如果错误函数被设计为静默)。
// 或者断言有错误输出(如果错误函数打印了信息)。
// 这里我们不做具体断言,因为 test_errors.h 的实现未知。
// 可以输出以供调试
// std::cout << "stdout: " << output << std::endl;
// std::cout << "stderr: " << errors << std::endl;
}
// 边界条件测试:无参数 main 函数(本身就是无参数)
// 此测试用例强调 main 函数不接受参数,但我们的 main 函数确实如此。
// 没有实际的边界值需要测试,因为 main 函数签名固定。
// 异常输入测试:不适用,因为 main 函数无参数。
// 特殊场景测试:验证 main 函数在多次调用下的行为(如果需要)。
// 注意:多次调用 main 通常不是预期用法,但我们可以测试其幂等性(如果函数设计如此)。
TEST(MainTest, MainCanBeCalledMultipleTimes) {
// 第一次调用
testing::internal::CaptureStdout();
testing::internal::CaptureStderr();
int result1 = main();
std::string output1 = testing::internal::GetCapturedStdout();
std::string errors1 = testing::internal::GetCapturedStderr();
EXPECT_EQ(result1, 0);
// 第二次调用
testing::internal::CaptureStdout();
testing::internal::CaptureStderr();
int result2 = main();
std::string output2 = testing::internal::GetCapturedStdout();
std::string errors2 = testing::internal::GetCapturedStderr();
EXPECT_EQ(result2, 0);
// 可选:比较两次调用的输出是否一致(如果函数有确定输出)。
// 由于 test_errors.h 中的函数可能有副作用(如内存泄漏),输出可能不同。
// 这里我们不做断言。
}
// 集成测试:验证 main 函数调用的所有函数都被执行。
// 这可以通过 mock 或 spy 来实现,但这里我们假设 test_errors.h 中的函数
// 有可观察的副作用(如写入文件、全局变量)。
// 由于 test_errors.h 的实现未知,我们无法编写具体断言。
// 作为示例,我们假设 test_file_leak() 会创建一个临时文件。
// 我们可以检查文件是否被创建(如果知道文件名)。
// 这里我们跳过,因为需要知道实现细节。
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}