#include "gtest/gtest.h" #include "src/memory.cpp" #include #include #include // 注意:由于原函数设计为演示错误,直接调用会导致内存泄漏、重复释放或文件泄漏。 // 因此,测试用例将重点验证这些错误行为是否被正确触发,或者通过特殊手段进行检测。 // 在实际项目中,应使用内存检测工具(如Valgrind, AddressSanitizer)或文件句柄监控来验证泄漏。 // 以下测试用例主要展示如何构建测试框架和断言,但部分测试可能无法直接通过断言验证错误本身。 // 测试 test_memory_leak // 该函数本身就会泄漏内存,无法通过返回值或直接副作用断言。 // 通常需要外部工具检测。这里我们仅确保函数可以无异常执行。 TEST(MemoryTest, MemoryLeakFunctionRuns) { // 期望函数可以正常执行完毕,不崩溃。 EXPECT_NO_FATAL_FAILURE(test_memory_leak()); // 注意:此测试通过并不意味着没有内存泄漏,只是函数被调用了。 } // 测试 test_double_free // 该函数会重复释放内存,通常会导致程序崩溃(如abort)。 // 在Google Test中,我们可以预期它会因重复释放而触发致命错误(如SIGABRT)。 // 使用 EXPECT_DEATH 来断言进程会因重复释放而终止。 TEST(MemoryTest, DoubleFreeCausesDeath) { // 期望调用 test_double_free 会导致进程终止(例如,因重复释放而abort)。 // 注意:EXPECT_DEATH 会 fork 一个子进程来运行测试语句。 // 正则表达式 ".*" 匹配任何死亡输出。 EXPECT_DEATH(test_double_free(), ".*"); } // 测试 test_file_leak // 该函数会打开文件但未关闭,导致文件句柄泄漏。 // 与内存泄漏类似,直接断言泄漏很困难,通常需要外部监控。 // 我们可以验证文件是否被成功创建(作为函数执行的副作用)。 // 并在测试后清理文件,同时确保函数调用本身不崩溃。 TEST(MemoryTest, FileLeakFunctionCreatesFile) { // 首先,确保测试文件不存在(清理之前的残留)。 std::remove("test.txt"); // 调用函数,期望它无异常执行并创建文件。 EXPECT_NO_FATAL_FAILURE(test_file_leak()); // 验证文件是否被创建(这是函数的主要可观察副作用)。 std::ifstream file("test.txt"); EXPECT_TRUE(file.good()); // 文件应成功打开(即存在)。 file.close(); // 测试结束后,清理文件。注意:原函数未关闭句柄,但进程退出后系统会回收。 // 为了测试环境干净,我们删除它。 std::remove("test.txt"); } // 边界/异常测试:这些函数无参数,因此没有直接的边界输入。 // 但我们可以考虑在调用前后检查系统状态(需要更复杂的工具集成)。 // 以下是一个示例,展示如果函数被修改为接受参数,可能的测试思路(当前不适用)。 /* // 假设函数签名变为:void test_memory_leak_with_size(size_t size); TEST(MemoryTest, MemoryLeakWithZeroSize) { // 测试分配大小为0的情况(行为可能是实现定义的)。 EXPECT_NO_FATAL_FAILURE(test_memory_leak_with_size(0)); } TEST(MemoryTest, MemoryLeakWithLargeSize) { // 测试分配极大内存(可能失败,但函数应处理或崩溃)。 // 使用 EXPECT_DEATH 或 EXPECT_THROW 取决于函数实现。 // 例如,如果 new 抛出 std::bad_alloc: // EXPECT_THROW(test_memory_leak_with_size(SIZE_MAX), std::bad_alloc); } */ int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }