#include "gtest/gtest.h" #include "src/memory.cpp" #include #include #include // 注意:由于源文件中的函数旨在演示错误,直接调用它们会导致未定义行为(如崩溃)。 // 因此,测试用例将主要验证这些函数的存在性,并说明在正常使用中应避免的错误模式。 // 对于内存泄漏和文件泄漏,我们无法在测试中断言其发生,但可以验证函数执行后没有立即崩溃。 // 对于重复释放,我们可以预期程序会崩溃,但这在单元测试中难以安全捕获。 // 以下测试用例旨在作为教学示例,展示如何为这类函数构建测试框架。 // 测试 test_memory_leak 函数的存在性和基本执行(不验证泄漏本身) TEST(MemoryTest, MemoryLeakFunctionExists) { // 该函数应该可以调用而不立即导致程序崩溃(尽管会导致内存泄漏) // 我们仅验证函数可以被调用。在实际项目中,应使用内存检测工具(如Valgrind)来验证泄漏。 EXPECT_NO_FATAL_FAILURE(test_memory_leak()); // 注意:EXPECT_NO_FATAL_FAILURE 仅保证测试进程本身不因致命错误而终止。 // 它无法检测到内存泄漏。 } // 测试 test_double_free 函数的存在性 // 警告:直接调用此函数会导致未定义行为(通常是崩溃)。 // 在单元测试环境中,我们无法安全地测试重复释放,因为它会使整个测试进程不稳定。 // 因此,此测试被标记为 DISABLED,不会在常规测试中运行。 // 它仅作为示例,说明如何标记危险的测试。 TEST(MemoryTest, DISABLED_DoubleFreeFunctionExists) { // 此测试被禁用,因为 test_double_free() 会导致崩溃。 // 在实际场景中,应通过代码审查或静态分析来避免此类错误。 // test_double_free(); // 这行代码被注释掉,因为调用它会崩溃。 SUCCEED(); // 仅表示测试框架存在 } // 测试 test_file_leak 函数的存在性和基本执行 TEST(MemoryTest, FileLeakFunctionExists) { // 调用函数,验证其可以执行而不立即崩溃。 // 文件 "test.txt" 可能会被创建并保持打开状态。 EXPECT_NO_FATAL_FAILURE(test_file_leak()); // 可选:检查文件是否被创建(但请注意,文件句柄仍处于泄漏状态)。 // 由于文件可能被其他进程锁定,此处不进行断言。 // 清理:尝试删除可能创建的文件(如果存在且未被锁定)。 std::remove("test.txt"); } // 边界和异常测试:由于这些函数没有参数,无法进行传统的边界值测试。 // 但我们可以创建辅助测试来演示正确的内存和文件管理实践,作为对比。 TEST(MemoryTest, CorrectMemoryManagement) { // 正确分配和释放内存 int* data = new int[100]; ASSERT_NE(data, nullptr); data[0] = 42; EXPECT_EQ(data[0], 42); delete[] data; // 正确释放 // 注意:释放后不应再访问 data。 } TEST(MemoryTest, CorrectFileManagement) { // 正确打开和关闭文件(使用C++风格,但原理相同) const char* filename = "correct_test.txt"; FILE* fp = fopen(filename, "w"); ASSERT_NE(fp, nullptr); fprintf(fp, "Hello, world!"); int closeResult = fclose(fp); EXPECT_EQ(closeResult, 0); // fclose 成功应返回 0 // 验证文件内容(可选) std::ifstream inFile(filename); std::string content; std::getline(inFile, content); EXPECT_EQ(content, "Hello, world!"); inFile.close(); std::remove(filename); // 清理测试文件 } // 主函数,通常由 gtest 框架提供,但在此文件中明确写出以确保可编译。 int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }