- 并发安全:PowerManger 新增 m_stateMutex,保护 m_pmCurrentState / m_currentDisBreakerState / m_CcuColCmd / faultCode,并封装 addFaultCode/clearFaultCodes/getFaultCodes 访问器 - SystemData 新增跨线程读访问器(getDynVoltageLink/getPowerBusStatus/ getDcdcStatus/getDeviceCommonStatus 等)及配电故障码集合加锁访问 - upmsg buildMsg / httpserver pushSystemData / LowerCommManager 均改为 持锁快照,避免 listen 线程与 comm 线程撕裂读写 - 修复析构顺序:先删 httpServer 再删其他对象,避免 use-after-free - 修复 ccuState reserved2 越界读(协议预留 2 字节,结构体仅声明 1), 修正 coutMsg 中 SOC 门限/功率限制字段打印 - udpComm::sendDisSysCmd 不再吞掉异常,返回 sendMsg 实际结果并记录 ERROR, 新增 SendDisSysCmdFailsWithoutSocket 单测 - 新增 fullFeeder 全类型 UDP 集成仿真器与 fetch-data/clean-data 脚本, .gitignore 补充 SQLite 运行期文件与 fullFeeder 二进制
186 lines
6.4 KiB
C++
186 lines
6.4 KiB
C++
//=======================================================================
|
||
// UdpCommTest: udpComm 纯逻辑函数(校验和、消息头识别、校验解析、日期)
|
||
// 仅链接现有 udpcomm/udpComm.cpp(+ MOOS 提供 MOOSTime 等符号)。
|
||
//=======================================================================
|
||
#include <gtest/gtest.h>
|
||
#include <cstring>
|
||
#include "udpcomm/udpComm.h"
|
||
|
||
TEST(UdpCommTest, CalculateChecksum)
|
||
{
|
||
udpComm u;
|
||
unsigned char data[5] = {1, 2, 3, 4, 5};
|
||
// 2 参:sum 覆盖 size - sizeof(Checksum)=size-4 字节
|
||
EXPECT_EQ(u.calculateChecksum(data, 4), 0u);
|
||
EXPECT_EQ(u.calculateChecksum(data, 5), 1u); // 只 sum data[0]=1
|
||
EXPECT_EQ(u.calculateChecksum(data, 6), 3u); // sum data[0..1]=1+2
|
||
// 3 参:覆盖 dataSize - checkSize 字节
|
||
EXPECT_EQ(u.calculateChecksum(data, 5, 2), 6u); // sum data[0..2]=1+2+3
|
||
EXPECT_EQ(u.calculateChecksum(data, 5, 1), 10u);// sum data[0..3]
|
||
}
|
||
|
||
TEST(UdpCommTest, GetMsgId)
|
||
{
|
||
udpComm u;
|
||
m_header h{};
|
||
char buf[sizeof(m_header)];
|
||
unsigned short id = 0;
|
||
|
||
// DIS 头
|
||
h.start1 = DIS_MSG_HEAD1;
|
||
h.start2 = DIS_MSG_HEAD2;
|
||
h.id = DIS_HVBUS_FB_ID;
|
||
memcpy(buf, &h, sizeof(h));
|
||
EXPECT_TRUE(u.getMsgId(buf, sizeof(buf), id));
|
||
EXPECT_EQ(id, DIS_HVBUS_FB_ID);
|
||
|
||
// CCU 头
|
||
h.start1 = CCU_UDPMSG_START1;
|
||
h.start2 = CCU_UDPMSG_START2;
|
||
h.id = CCU_STATE_FB_ID;
|
||
memcpy(buf, &h, sizeof(h));
|
||
EXPECT_TRUE(u.getMsgId(buf, sizeof(buf), id));
|
||
EXPECT_EQ(id, CCU_STATE_FB_ID);
|
||
|
||
// 非法头
|
||
h.start1 = 0x11;
|
||
h.start2 = 0x22;
|
||
memcpy(buf, &h, sizeof(h));
|
||
EXPECT_FALSE(u.getMsgId(buf, sizeof(buf), id));
|
||
|
||
// 长度不足 m_header → 拒绝(不读越界)
|
||
EXPECT_FALSE(u.getMsgId(buf, sizeof(m_header) - 1, id));
|
||
EXPECT_FALSE(u.getMsgId(NULL, sizeof(m_header), id));
|
||
}
|
||
|
||
TEST(UdpCommTest, GetMsgFromBuffCcu)
|
||
{
|
||
udpComm u;
|
||
msg_CcuStateFbMsg m;
|
||
memset(&m, 0, sizeof(m));
|
||
m.header.start1 = CCU_UDPMSG_START1;
|
||
m.header.start2 = CCU_UDPMSG_START2;
|
||
m.header.id = CCU_STATE_FB_ID;
|
||
m.data.ins_soc = 42;
|
||
m.data.dyn_soc = 66;
|
||
m.data.fc_status = 0x04;
|
||
m.checkCode = u.calculateChecksum((unsigned char*)&m, sizeof(m));
|
||
|
||
msg_CcuStateFbMsg out{};
|
||
EXPECT_TRUE(u.getMsgFromBuff((char*)&m, sizeof(m), out));
|
||
EXPECT_EQ(out.data.ins_soc, 42u);
|
||
EXPECT_EQ(out.data.dyn_soc, 66u);
|
||
EXPECT_EQ(out.data.fc_status, 0x04u);
|
||
|
||
// 篡改数据 → 校验失败
|
||
m.data.dyn_soc = 99;
|
||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, sizeof(m), out));
|
||
|
||
// 截断帧(长度不足)→ 拒绝,不写输出
|
||
m.data.dyn_soc = 66;
|
||
m.checkCode = u.calculateChecksum((unsigned char*)&m, sizeof(m));
|
||
msg_CcuStateFbMsg untouched{};
|
||
untouched.data.ins_soc = 0xEE;
|
||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, sizeof(m) - 1, untouched));
|
||
EXPECT_EQ(untouched.data.ins_soc, 0xEEu);
|
||
|
||
// 超长帧(长度超出)→ 接受,忽略尾字节
|
||
unsigned char longBuf[sizeof(m) + 16];
|
||
memset(longBuf, 0, sizeof(longBuf));
|
||
memcpy(longBuf, &m, sizeof(m));
|
||
msg_CcuStateFbMsg outLong{};
|
||
EXPECT_TRUE(u.getMsgFromBuff((char*)longBuf, sizeof(longBuf), outLong));
|
||
EXPECT_EQ(outLong.data.ins_soc, 42u);
|
||
|
||
// 空指针 / 长度不足 → 拒绝
|
||
EXPECT_FALSE(u.getMsgFromBuff(NULL, sizeof(m), out));
|
||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, 0, out));
|
||
}
|
||
|
||
TEST(UdpCommTest, GetMsgFromBuffDis)
|
||
{
|
||
udpComm u;
|
||
msg_disHighVolBusFbMsg m;
|
||
memset(&m, 0, sizeof(m));
|
||
m.header.start1 = DIS_MSG_HEAD1;
|
||
m.header.start2 = DIS_MSG_HEAD2;
|
||
m.header.id = DIS_HVBUS_FB_ID;
|
||
m.data.fuelCellCircuitBreaker = 0x55;
|
||
m.data.powerBusVoltage = 5200;
|
||
m.checkCode = (cChecksum)(u.calculateChecksum((unsigned char*)&m, sizeof(m), sizeof(cChecksum)) & 0xFF);
|
||
|
||
msg_disHighVolBusFbMsg out{};
|
||
EXPECT_TRUE(u.getMsgFromBuff((char*)&m, sizeof(m), out));
|
||
EXPECT_EQ(out.data.fuelCellCircuitBreaker, 0x55u);
|
||
EXPECT_EQ(out.data.powerBusVoltage, 5200u);
|
||
|
||
// 篡改 → 校验失败
|
||
m.data.fuelCellCircuitBreaker = 0xAA;
|
||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, sizeof(m), out));
|
||
|
||
// 截断帧 → 拒绝
|
||
m.data.fuelCellCircuitBreaker = 0x55;
|
||
m.checkCode = (cChecksum)(u.calculateChecksum((unsigned char*)&m, sizeof(m), sizeof(cChecksum)) & 0xFF);
|
||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, sizeof(m) - 1, out));
|
||
}
|
||
|
||
TEST(UdpCommTest, PushMsgToQueueLengthGuard)
|
||
{
|
||
udpComm u;
|
||
msg_CcuStateFbMsg m;
|
||
memset(&m, 0, sizeof(m));
|
||
m.header.start1 = CCU_UDPMSG_START1;
|
||
m.header.start2 = CCU_UDPMSG_START2;
|
||
m.header.id = CCU_STATE_FB_ID;
|
||
m.data.ins_soc = 42;
|
||
m.checkCode = u.calculateChecksum((unsigned char*)&m, sizeof(m));
|
||
|
||
// 合法帧入队成功
|
||
EXPECT_TRUE(u.pushMsgToQueue((unsigned char*)&m, sizeof(m)));
|
||
EXPECT_EQ(u.m_qReceiveCcuStateBuffer.size(), 1u);
|
||
EXPECT_EQ(u.m_qReceiveCcuStateBuffer.front().second.data.ins_soc, 42u);
|
||
|
||
// 空指针 / 长度不足 m_header → 拒绝
|
||
EXPECT_FALSE(u.pushMsgToQueue(NULL, sizeof(m)));
|
||
EXPECT_FALSE(u.pushMsgToQueue((unsigned char*)&m, sizeof(m_header) - 1));
|
||
|
||
// 截断帧(合法头 + 校验和,但长度不足整包)→ 拒绝入队
|
||
msg_CcuStateFbMsg shortM;
|
||
memset(&shortM, 0, sizeof(shortM));
|
||
shortM.header.start1 = CCU_UDPMSG_START1;
|
||
shortM.header.start2 = CCU_UDPMSG_START2;
|
||
shortM.header.id = CCU_STATE_FB_ID;
|
||
shortM.checkCode = u.calculateChecksum((unsigned char*)&shortM, sizeof(shortM) - 8);
|
||
size_t before = u.m_qReceiveCcuStateBuffer.size();
|
||
EXPECT_FALSE(u.pushMsgToQueue((unsigned char*)&shortM, sizeof(shortM) - 8));
|
||
EXPECT_EQ(u.m_qReceiveCcuStateBuffer.size(), before);
|
||
}
|
||
|
||
TEST(UdpCommTest, GetDate)
|
||
{
|
||
udpComm u;
|
||
unsigned short year = 0;
|
||
unsigned char month = 0, day = 0, hour = 0, minute = 0, second = 0, ms = 0;
|
||
EXPECT_TRUE(u.getDate(year, month, day, hour, minute, second, ms));
|
||
EXPECT_GE(year, 2000u);
|
||
EXPECT_LE(year, 2100u);
|
||
EXPECT_GE(month, 1u); EXPECT_LE(month, 12u);
|
||
EXPECT_GE(day, 1u); EXPECT_LE(day, 31u);
|
||
EXPECT_LE(hour, 23u);
|
||
EXPECT_LE(minute, 59u);
|
||
EXPECT_LE(second, 59u);
|
||
}
|
||
|
||
TEST(UdpCommTest, SendDisSysCmdFailsWithoutSocket)
|
||
{
|
||
udpComm u; // 默认构造 udpScoket=nullptr,sendMsg 应返回 false
|
||
disHighVolBusCmd c1{};
|
||
disHighAVolBusCmd c2{};
|
||
disHighBVolBusCmd c3{};
|
||
disLowBusCmd c4{};
|
||
EXPECT_FALSE(u.sendDisSysCmd(c1));
|
||
EXPECT_FALSE(u.sendDisSysCmd(c2));
|
||
EXPECT_FALSE(u.sendDisSysCmd(c3));
|
||
EXPECT_FALSE(u.sendDisSysCmd(c4));
|
||
}
|