cdemo/tests/test_memory.cpp

76 lines
3.6 KiB
C++
Raw Permalink Normal View History

2026-04-14 02:49:57 +00:00
#include "gtest/gtest.h"
#include "src/memory.cpp"
#include <cstdio>
#include <cstdlib>
#include <fstream>
// 注意:由于原函数设计为演示错误,直接调用会导致内存泄漏、重复释放或文件泄漏。
// 因此,测试用例将重点验证这些错误行为是否被正确触发,或者通过特殊手段进行检测。
// 在实际项目中应使用内存检测工具如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();
}