From f1210b48e2509776c3e26a488045060ed17a6cca Mon Sep 17 00:00:00 2001 From: linianlin Date: Thu, 18 Jun 2026 13:26:08 +0800 Subject: [PATCH] =?UTF-8?q?AI=20=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/CMakeLists.txt | 25 ++++ tests/test_app.cpp | 304 +++++++++++++++++++++++++++++++++++++++++++ tests/test_dau.cpp | 109 ++++++++++++++++ tests/test_ppu.cpp | 131 +++++++++++++++++++ 4 files changed, 569 insertions(+) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/test_app.cpp create mode 100644 tests/test_dau.cpp create mode 100644 tests/test_ppu.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..419686a --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.10.0) +project(test_net_env_project) +include(FetchContent) +if (MSVC) + add_compile_options(/utf-8) +endif() +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include) + +include(CTest) +enable_testing() + +add_executable(test_net_env_project test_dau.cpp ../src/dau.cpp test_app.cpp ../src/dsu.cpp test_ppu.cpp ../src/ppu.cpp) + +target_link_libraries(test_net_env_project gtest gmock gtest_main) +include(GoogleTest) +gtest_discover_tests(test_net_env_project) \ No newline at end of file diff --git a/tests/test_app.cpp b/tests/test_app.cpp new file mode 100644 index 0000000..db85118 --- /dev/null +++ b/tests/test_app.cpp @@ -0,0 +1,304 @@ +#include +#include +#include +#include +#include +#include "app.hpp" + +/** + * 测试文件: test_app.cpp + * 被测文件: app.cpp (dsu namespace) + * 说明: 由于s_storage为静态全局变量,无法在测试中直接重置, + * 各测试用例使用唯一的channelId以避免数据干扰。 + * 注意:StorageStatus 和 QueryCondition 定义在全局命名空间。 + */ + +// ==================== DSU_Write 测试 ==================== + +class DSUWriteTest : public ::testing::Test { +protected: + uint32_t channelId = 0; + time_t timestamp = 1000000; + + void SetUp() override { + static uint32_t channelCounter = 2000; + channelId = channelCounter++; + } +}; + +// 测试正常写入数据流 +TEST_F(DSUWriteTest, testDSUWriteNormalInput) { + std::vector data = {0x01, 0x02, 0x03, 0x04}; + bool result = dsu::DSU_Write(data, channelId, timestamp); + EXPECT_TRUE(result); +} + +// 测试空数据写入应返回false +TEST_F(DSUWriteTest, testDSUWriteEmptyData) { + std::vector data; + bool result = dsu::DSU_Write(data, channelId, timestamp); + EXPECT_FALSE(result); +} + +// 测试channelId和timestamp为0的边界值 +TEST_F(DSUWriteTest, testDSUWriteBoundaryZeroValues) { + std::vector data = {0xFF}; + bool result = dsu::DSU_Write(data, 0, 0); + EXPECT_TRUE(result); +} + +// 测试channelId和timestamp为最大值 +TEST_F(DSUWriteTest, testDSUWriteMaxValues) { + std::vector data = {0xAB, 0xCD}; + bool result = dsu::DSU_Write(data, UINT32_MAX, static_cast(UINT32_MAX)); + EXPECT_TRUE(result); +} + +// 测试单字节数据写入 +TEST_F(DSUWriteTest, testDSUWriteSingleByte) { + std::vector data = {0x42}; + bool result = dsu::DSU_Write(data, channelId, timestamp); + EXPECT_TRUE(result); +} + +// 测试大数据块写入 +TEST_F(DSUWriteTest, testDSUWriteLargeData) { + std::vector data(1024, 0xAA); + bool result = dsu::DSU_Write(data, channelId, timestamp); + EXPECT_TRUE(result); +} + +// ==================== DSU_CheckDisk 测试 ==================== + +// 测试磁盘健康状态检查(正常状态) +TEST(DSUCheckDiskTest, testDSUCheckDiskHealthy) { + StorageStatus status = dsu::DSU_CheckDisk(); + EXPECT_TRUE(status == StorageStatus::Healthy || + status == StorageStatus::Full); +} + +// 测试磁盘存储满告警(写入超过1000条触发Full) +TEST(DSUCheckDiskTest, testDSUCheckDiskFull) { + uint32_t fillChannel = 9000; + for (int i = 0; i < 1005; ++i) { + std::vector data = {static_cast(i & 0xFF)}; + dsu::DSU_Write(data, fillChannel, static_cast(i)); + } + StorageStatus status = dsu::DSU_CheckDisk(); + EXPECT_EQ(status, StorageStatus::Full); +} + +// ==================== DSU_Query 测试 ==================== + +class DSUQueryTest : public ::testing::Test { +protected: + uint32_t channelId = 0; + + void SetUp() override { + static uint32_t channelCounter = 5000; + channelId = channelCounter++; + } +}; + +// 测试正常查询返回匹配数据 +TEST_F(DSUQueryTest, testDSUQueryNormalInput) { + std::vector data1 = {0x01, 0x02}; + std::vector data2 = {0x03, 0x04}; + dsu::DSU_Write(data1, channelId, 100); + dsu::DSU_Write(data2, channelId, 200); + + QueryCondition condition; + condition.channelId = channelId; + condition.startTime = 100; + condition.endTime = 200; + condition.maxResults = 10; + + std::vector> results; + std::string log; + bool ret = dsu::DSU_Query(condition, results, log); + + EXPECT_TRUE(ret); + EXPECT_EQ(results.size(), 2u); + EXPECT_EQ(results[0], data1); + EXPECT_EQ(results[1], data2); +} + +// 测试无匹配数据时返回false +TEST_F(DSUQueryTest, testDSUQueryNoMatch) { + QueryCondition condition; + condition.channelId = 99999; + condition.startTime = 0; + condition.endTime = 100; + condition.maxResults = 10; + + std::vector> results; + std::string log; + bool ret = dsu::DSU_Query(condition, results, log); + + EXPECT_FALSE(ret); + EXPECT_TRUE(results.empty()); +} + +// 测试maxResults限制查询结果数量 +TEST_F(DSUQueryTest, testDSUQueryMaxResultsLimit) { + for (int i = 0; i < 5; ++i) { + std::vector data = {static_cast(i)}; + dsu::DSU_Write(data, channelId, static_cast(300 + i)); + } + + QueryCondition condition; + condition.channelId = channelId; + condition.startTime = 300; + condition.endTime = 400; + condition.maxResults = 3; + + std::vector> results; + std::string log; + bool ret = dsu::DSU_Query(condition, results, log); + + EXPECT_TRUE(ret); + EXPECT_LE(results.size(), 3u); +} + +// 测试时间范围精确查询 +TEST_F(DSUQueryTest, testDSUQueryTimeRange) { + std::vector data1 = {0x10}; + std::vector data2 = {0x20}; + std::vector data3 = {0x30}; + dsu::DSU_Write(data1, channelId, 500); + dsu::DSU_Write(data2, channelId, 600); + dsu::DSU_Write(data3, channelId, 700); + + QueryCondition condition; + condition.channelId = channelId; + condition.startTime = 550; + condition.endTime = 650; + condition.maxResults = 10; + + std::vector> results; + std::string log; + bool ret = dsu::DSU_Query(condition, results, log); + + EXPECT_TRUE(ret); + EXPECT_EQ(results.size(), 1u); + EXPECT_EQ(results[0], data2); +} + +// 测试查询日志包含结果数量信息 +TEST_F(DSUQueryTest, testDSUQueryLogOutput) { + std::vector data = {0x01}; + dsu::DSU_Write(data, channelId, 100); + + QueryCondition condition; + condition.channelId = channelId; + condition.startTime = 100; + condition.endTime = 100; + condition.maxResults = 10; + + std::vector> results; + std::string log; + dsu::DSU_Query(condition, results, log); + + EXPECT_FALSE(log.empty()); + EXPECT_NE(log.find("Query returned"), std::string::npos); +} + +// ==================== DSU_Replay 测试 ==================== + +class DSUReplayTest : public ::testing::Test { +protected: + uint32_t channelId = 0; + + void SetUp() override { + static uint32_t channelCounter = 7000; + channelId = channelCounter++; + } +}; + +// 测试正常回放数据 +TEST_F(DSUReplayTest, testDSUReplayNormalInput) { + std::vector data1 = {0x01, 0x02}; + std::vector data2 = {0x03, 0x04}; + dsu::DSU_Write(data1, channelId, 100); + dsu::DSU_Write(data2, channelId, 200); + + QueryCondition condition; + condition.channelId = channelId; + condition.startTime = 100; + condition.endTime = 200; + condition.maxResults = 10; + + std::vector replayOutput; + std::string log; + bool ret = dsu::DSU_Replay(condition, replayOutput, log); + + EXPECT_TRUE(ret); + EXPECT_EQ(replayOutput.size(), 4u); + EXPECT_EQ(replayOutput[0], 0x01); + EXPECT_EQ(replayOutput[1], 0x02); + EXPECT_EQ(replayOutput[2], 0x03); + EXPECT_EQ(replayOutput[3], 0x04); +} + +// 测试无数据时回放返回false +TEST_F(DSUReplayTest, testDSUReplayNoData) { + QueryCondition condition; + condition.channelId = 88888; + condition.startTime = 0; + condition.endTime = 100; + condition.maxResults = 10; + + std::vector replayOutput; + std::string log; + bool ret = dsu::DSU_Replay(condition, replayOutput, log); + + EXPECT_FALSE(ret); +} + +// 测试多数据块按序拼接回放 +TEST_F(DSUReplayTest, testDSUReplayMultipleBlocks) { + std::vector data1 = {0xAA}; + std::vector data2 = {0xBB, 0xCC}; + std::vector data3 = {0xDD, 0xEE, 0xFF}; + dsu::DSU_Write(data1, channelId, 100); + dsu::DSU_Write(data2, channelId, 200); + dsu::DSU_Write(data3, channelId, 300); + + QueryCondition condition; + condition.channelId = channelId; + condition.startTime = 100; + condition.endTime = 300; + condition.maxResults = 10; + + std::vector replayOutput; + std::string log; + bool ret = dsu::DSU_Replay(condition, replayOutput, log); + + EXPECT_TRUE(ret); + EXPECT_EQ(replayOutput.size(), 6u); + EXPECT_EQ(replayOutput[0], 0xAA); + EXPECT_EQ(replayOutput[1], 0xBB); + EXPECT_EQ(replayOutput[2], 0xCC); + EXPECT_EQ(replayOutput[3], 0xDD); + EXPECT_EQ(replayOutput[4], 0xEE); + EXPECT_EQ(replayOutput[5], 0xFF); +} + +// 测试回放日志包含完成信息 +TEST_F(DSUReplayTest, testDSUReplayLogContainsInfo) { + std::vector data = {0x01}; + dsu::DSU_Write(data, channelId, 100); + + QueryCondition condition; + condition.channelId = channelId; + condition.startTime = 100; + condition.endTime = 100; + condition.maxResults = 10; + + std::vector replayOutput; + std::string log; + dsu::DSU_Replay(condition, replayOutput, log); + + EXPECT_FALSE(log.empty()); + EXPECT_NE(log.find("Replay completed"), std::string::npos); +} diff --git a/tests/test_dau.cpp b/tests/test_dau.cpp new file mode 100644 index 0000000..e472c80 --- /dev/null +++ b/tests/test_dau.cpp @@ -0,0 +1,109 @@ +#include +#include "app.hpp" +#include +#include + +using namespace dau; + +class DAUTest : public ::testing::Test { +protected: + void SetUp() override { + DAU_SetSleep(false); + } +}; + +TEST_F(DAUTest, testDAU_Process_NormalInput) { + RawDataFrame input{}; + ValidData output{}; + std::string errorLog; + + input.len = 8; + for (int i = 0; i < 8; ++i) input.data[i] = i; + input.timestamp = 12345; + input.busType = static_cast(1); + + bool result = DAU_Process(input, output, errorLog); + + EXPECT_TRUE(result); + EXPECT_EQ(output.dataLen, 8); + EXPECT_EQ(output.timestamp, 12345); + EXPECT_EQ(output.sourceBus, static_cast(1)); + EXPECT_EQ(errorLog, ""); +} + +TEST_F(DAUTest, testDAU_Process_SleepMode) { + DAU_SetSleep(true); + RawDataFrame input{}; + ValidData output{}; + std::string errorLog; + + input.len = 8; + input.data[0] = 0x01; + bool result = DAU_Process(input, output, errorLog); + + EXPECT_FALSE(result); + EXPECT_NE(errorLog.find("Sleep mode"), std::string::npos); +} + +TEST_F(DAUTest, testDAU_Process_InvalidLengthZero) { + RawDataFrame input{}; + ValidData output{}; + std::string errorLog; + + input.len = 0; + bool result = DAU_Process(input, output, errorLog); + + EXPECT_FALSE(result); + EXPECT_NE(errorLog.find("Invalid data length"), std::string::npos); +} + +TEST_F(DAUTest, testDAU_Process_InvalidLengthMax) { + RawDataFrame input{}; + ValidData output{}; + std::string errorLog; + + input.len = 65; + bool result = DAU_Process(input, output, errorLog); + + EXPECT_FALSE(result); + EXPECT_NE(errorLog.find("Invalid data length"), std::string::npos); +} + +TEST_F(DAUTest, testDAU_Process_ErrorFrame) { + RawDataFrame input{}; + ValidData output{}; + std::string errorLog; + + input.len = 8; + memset(input.data, 0xFF, 8); + bool result = DAU_Process(input, output, errorLog); + + EXPECT_FALSE(result); + EXPECT_NE(errorLog.find("Error frame detected"), std::string::npos); +} + +TEST_F(DAUTest, testDAU_SetSleep_EnableDisable) { + DAU_SetSleep(true); + RawDataFrame input{}; + ValidData output{}; + std::string errorLog; + input.len = 1; + input.data[0] = 0x01; + EXPECT_FALSE(DAU_Process(input, output, errorLog)); + + DAU_SetSleep(false); + EXPECT_TRUE(DAU_Process(input, output, errorLog)); +} + +TEST_F(DAUTest, testDAU_GetBusLoad_InitialAndIncrement) { + uint32_t initialLoad = DAU_GetBusLoad(); + + RawDataFrame input{}; + ValidData output{}; + std::string errorLog; + input.len = 1; + input.data[0] = 0x01; + + DAU_Process(input, output, errorLog); + EXPECT_EQ(DAU_GetBusLoad(), initialLoad + 5); +} diff --git a/tests/test_ppu.cpp b/tests/test_ppu.cpp new file mode 100644 index 0000000..1f381ff --- /dev/null +++ b/tests/test_ppu.cpp @@ -0,0 +1,131 @@ +#include +#include "app.hpp" +#include +#include + +using namespace ppu; + +// 辅助函数:创建 CanFrame +CanFrame CreateCanFrame(uint32_t id, bool isExtended, bool isCanFd, uint8_t dataLen) { + CanFrame frame; + frame.id = id; + frame.isExtended = isExtended; + frame.isCanFd = isCanFd; + frame.dataLen = dataLen; + frame.timestamp = 1000; + std::memset(frame.data, 0, sizeof(frame.data)); + for (uint8_t i = 0; i < dataLen && i < 64; ++i) { + frame.data[i] = i; + } + return frame; +} + +// ================= PPU_Check 测试用例 ================= + +TEST(PPU_Check_Test, Normal_Standard_CAN20) { + CanFrame frame = CreateCanFrame(0x100, false, false, 8); + std::string reason; + EXPECT_TRUE(PPU_Check(frame, reason)); +} + +TEST(PPU_Check_Test, Normal_Extended_CANFD) { + CanFrame frame = CreateCanFrame(0x1FFFFFFF, true, true, 64); + std::string reason; + EXPECT_TRUE(PPU_Check(frame, reason)); +} + +TEST(PPU_Check_Test, Boundary_Standard_ID_Max) { + CanFrame frame = CreateCanFrame(0x7FF, false, false, 8); + std::string reason; + EXPECT_TRUE(PPU_Check(frame, reason)); +} + +TEST(PPU_Check_Test, Boundary_Extended_ID_Max) { + CanFrame frame = CreateCanFrame(0x1FFFFFFF, true, false, 8); + std::string reason; + EXPECT_TRUE(PPU_Check(frame, reason)); +} + +TEST(PPU_Check_Test, Boundary_DataLen_Zero) { + CanFrame frame = CreateCanFrame(0x100, false, false, 0); + std::string reason; + EXPECT_TRUE(PPU_Check(frame, reason)); +} + +TEST(PPU_Check_Test, Exception_DataLen_Exceeds_64) { + CanFrame frame = CreateCanFrame(0x100, false, true, 65); + std::string reason; + EXPECT_FALSE(PPU_Check(frame, reason)); + EXPECT_NE(reason.find("exceeds maximum (64)"), std::string::npos); +} + +TEST(PPU_Check_Test, Exception_CAN20_DataLen_Exceeds_8) { + CanFrame frame = CreateCanFrame(0x100, false, false, 9); + std::string reason; + EXPECT_FALSE(PPU_Check(frame, reason)); + EXPECT_NE(reason.find("exceeds 8 bytes"), std::string::npos); +} + +TEST(PPU_Check_Test, Exception_Standard_ID_Exceeds_11bit) { + CanFrame frame = CreateCanFrame(0x800, false, false, 8); + std::string reason; + EXPECT_FALSE(PPU_Check(frame, reason)); + EXPECT_NE(reason.find("exceeds 11-bit range"), std::string::npos); +} + +TEST(PPU_Check_Test, Exception_Extended_ID_Exceeds_29bit) { + CanFrame frame = CreateCanFrame(0x20000000, true, false, 8); + std::string reason; + EXPECT_FALSE(PPU_Check(frame, reason)); + EXPECT_NE(reason.find("exceeds 29-bit range"), std::string::npos); +} + +// ================= PPU_Convert 测试用例 ================= + +TEST(PPU_Convert_Test, Normal_CAN20_to_CANFD) { + CanFrame input = CreateCanFrame(0x100, false, false, 8); + CompatibleFrame output; + std::string log; + EXPECT_TRUE(PPU_Convert(input, output, log)); + EXPECT_EQ(output.dataLen, 8); + EXPECT_NE(log.find("CAN2.0->CANFD"), std::string::npos); + EXPECT_EQ(output.id, input.id); +} + +TEST(PPU_Convert_Test, Normal_CANFD_to_CAN20_No_Truncation) { + CanFrame input = CreateCanFrame(0x100, false, true, 8); + CompatibleFrame output; + std::string log; + EXPECT_TRUE(PPU_Convert(input, output, log)); + EXPECT_EQ(output.dataLen, 8); + EXPECT_NE(log.find("CANFD->CAN2.0"), std::string::npos); +} + +TEST(PPU_Convert_Test, Normal_CANFD_to_CAN20_With_Truncation) { + CanFrame input = CreateCanFrame(0x100, false, true, 64); + CompatibleFrame output; + std::string log; + EXPECT_TRUE(PPU_Convert(input, output, log)); + EXPECT_EQ(output.dataLen, 8); + EXPECT_NE(log.find("CANFD->CAN2.0"), std::string::npos); +} + +TEST(PPU_Convert_Test, Exception_Check_Failed) { + CanFrame input = CreateCanFrame(0x100, false, false, 9); // CAN2.0 len > 8 + CompatibleFrame output; + std::string log; + EXPECT_FALSE(PPU_Convert(input, output, log)); + EXPECT_NE(log.find("Convert rejected"), std::string::npos); +} + +TEST(PPU_Convert_Test, Special_Data_Copy_Verification) { + CanFrame input = CreateCanFrame(0x123, true, false, 4); + input.data[0] = 0xAA; input.data[1] = 0xBB; input.data[2] = 0xCC; input.data[3] = 0xDD; + CompatibleFrame output; + std::string log; + EXPECT_TRUE(PPU_Convert(input, output, log)); + EXPECT_EQ(output.data[0], 0xAA); + EXPECT_EQ(output.data[1], 0xBB); + EXPECT_EQ(output.data[2], 0xCC); + EXPECT_EQ(output.data[3], 0xDD); +} \ No newline at end of file