Files
H100PowerManger/test/until/SqliteTest.cpp
T
zjk e0488d513b 协议:按0824协议更新复合管控通信解析 + 新增燃料电池监控网页
- pmSysvariable/ccuUdpMsg: 域起始符改为0x40 0x40,域标识符重编号0x0001~0x0004,
  ccuState/ccuColCmd/ccuSetParmCmd 按新协议字段布局与字节序重写(状态248B/操控45B/参数28B)
- systemData/httpserver: 新增FC单片电压、甲醇制氢装置、DC/DC、尾气装置、一体化罐、
  供氢供氧流量、应急上浮等字段解析与WebSocket JSON推送
- 新增 /fcs 燃料电池监控页(fuelcell.h):实时数据显示 + 操控指令交互按钮,
  过滤日志推送消息避免界面闪烁
- SQLite/LowerCommManager/测试:更新建表列、解析打印与单元/集成测试适配新协议
2026-08-26 20:56:39 +08:00

256 lines
9.2 KiB
C++

//=======================================================================
// SqliteTest(gtest): 验证 SQLite 封装 10 个 insertData 写入正确。
// 不改动 SQLite 封装;用裸 sqlite3 打开同一文件读回验证。
//=======================================================================
#include <gtest/gtest.h>
#include <cstdio>
#include <string>
#include <unistd.h>
#include "sqlit3/SQLite.h"
#include "sqlit3/sqlite3.h"
static std::string tmpPath(const char* name) {
return std::string("/tmp/pmsqlite_") + name + "_" + std::to_string(::getpid()) + ".db";
}
static bool rawQueryInt(const std::string& path, const std::string& sql, long long& out) {
sqlite3* db = nullptr;
if (sqlite3_open(path.c_str(), &db) != SQLITE_OK) return false;
sqlite3_stmt* stmt = nullptr;
bool ok = false;
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) == SQLITE_OK) {
if (sqlite3_step(stmt) == SQLITE_ROW) { out = sqlite3_column_int64(stmt, 0); ok = true; }
}
if (stmt) sqlite3_finalize(stmt);
sqlite3_close(db);
return ok;
}
static bool rawCount(const std::string& path, const std::string& table, long long& out) {
return rawQueryInt(path, "SELECT COUNT(*) FROM " + table, out);
}
static bool rawQueryText(const std::string& path, const std::string& sql, std::string& out) {
sqlite3* db = nullptr;
if (sqlite3_open(path.c_str(), &db) != SQLITE_OK) return false;
sqlite3_stmt* stmt = nullptr;
bool ok = false;
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) == SQLITE_OK) {
if (sqlite3_step(stmt) == SQLITE_ROW) {
const unsigned char* t = sqlite3_column_text(stmt, 0);
if (t) { out = reinterpret_cast<const char*>(t); ok = true; }
}
}
if (stmt) sqlite3_finalize(stmt);
sqlite3_close(db);
return ok;
}
TEST(SqliteTest, InsertCcuStateReadBack)
{
std::string path = tmpPath("ccu");
{
SQLite db(path);
ASSERT_TRUE(db.createTable());
ccuState c{}; c.ins_soc = 42; c.dyn_soc = 66; c.fc_status = 4;
EXPECT_TRUE(db.insertData(c));
}
long long v = 0;
EXPECT_TRUE(rawQueryInt(path, "SELECT ins_soc FROM ccuState ORDER BY id DESC LIMIT 1", v));
EXPECT_EQ(v, 42);
EXPECT_TRUE(rawQueryInt(path, "SELECT dyn_soc FROM ccuState ORDER BY id DESC LIMIT 1", v));
EXPECT_EQ(v, 66);
EXPECT_TRUE(rawQueryInt(path, "SELECT fc_status FROM ccuState ORDER BY id DESC LIMIT 1", v));
EXPECT_EQ(v, 4);
std::remove(path.c_str());
}
TEST(SqliteTest, InsertDisHighVolBusStateReadBack)
{
std::string path = tmpPath("dihv");
{
SQLite db(path);
ASSERT_TRUE(db.createTable());
disHighVolBusState s{};
s.fuelCellCircuitBreaker = 1;
s.powerBusVoltage = 5200;
EXPECT_TRUE(db.insertData(s));
}
long long v = 0;
EXPECT_TRUE(rawQueryInt(path, "SELECT fuelCellCircuitBreaker FROM disHighVolBusState ORDER BY id DESC LIMIT 1", v));
EXPECT_EQ(v, 1);
EXPECT_TRUE(rawQueryInt(path, "SELECT powerBusVoltage FROM disHighVolBusState ORDER BY id DESC LIMIT 1", v));
EXPECT_EQ(v, 5200);
std::remove(path.c_str());
}
TEST(SqliteTest, InsertDisHighAVolBusStateReadBack)
{
std::string path = tmpPath("dihva");
{
SQLite db(path); ASSERT_TRUE(db.createTable());
disHighAVolBusState s{}; s.bowFTDevice123CircuitBreaker = 1; s.busbarBVoltage = 100;
EXPECT_TRUE(db.insertData(s));
}
long long v = 0;
EXPECT_TRUE(rawQueryInt(path, "SELECT bowFTDevice123CircuitBreaker FROM disHighAVolBusState", v));
EXPECT_EQ(v, 1);
EXPECT_TRUE(rawQueryInt(path, "SELECT busbarBVoltage FROM disHighAVolBusState", v));
EXPECT_EQ(v, 100);
std::remove(path.c_str());
}
TEST(SqliteTest, InsertDisLowMainBusStateReadBack)
{
std::string path = tmpPath("dilmb");
{
SQLite db(path); ASSERT_TRUE(db.createTable());
disLowMainBusState s{}; s.unit4InstrumentDC48VCircuitBreaker = 1;
EXPECT_TRUE(db.insertData(s));
}
long long v = 0;
EXPECT_TRUE(rawQueryInt(path, "SELECT unit4InstrumentDC48VCircuitBreaker FROM disLowMainBusState", v));
EXPECT_EQ(v, 1);
std::remove(path.c_str());
}
TEST(SqliteTest, InsertDisLowBusStateReadBack)
{
std::string path = tmpPath("dilb");
{
SQLite db(path); ASSERT_TRUE(db.createTable());
disLowBusState s{}; s.unit1CircuitBreaker = 1;
EXPECT_TRUE(db.insertData(s));
}
long long v = 0;
EXPECT_TRUE(rawQueryInt(path, "SELECT unit1CircuitBreaker FROM disLowBusState", v));
EXPECT_EQ(v, 1);
std::remove(path.c_str());
}
TEST(SqliteTest, InsertCommandsReadBack)
{
std::string path = tmpPath("cmd");
{
SQLite db(path); ASSERT_TRUE(db.createTable());
ccuColCmd cc{}; cc.heartbeat = 5; EXPECT_TRUE(db.insertData(cc));
disHighVolBusCmd c1{}; c1.dcdc5Module = 1; c1.coolingSystem = 1; EXPECT_TRUE(db.insertData(c1));
disHighAVolBusCmd c2{}; c2.xczCircuitBreaker = 1; EXPECT_TRUE(db.insertData(c2));
disLowMainBusCmd c3{}; c3.dcC1DCDistributionPanelCircuitBreaker = 1; EXPECT_TRUE(db.insertData(c3));
disLowBusCmd c4{}; c4.unit2CircuitBreaker = 1; EXPECT_TRUE(db.insertData(c4));
}
long long v = 0;
EXPECT_TRUE(rawQueryInt(path, "SELECT heartbeat FROM ccuColCmd", v)); EXPECT_EQ(v, 5);
EXPECT_TRUE(rawQueryInt(path, "SELECT dcdc5Module FROM disHighVolBusCmd", v)); EXPECT_EQ(v, 1);
EXPECT_TRUE(rawQueryInt(path, "SELECT xczCircuitBreaker FROM disHighAVolBusCmd", v)); EXPECT_EQ(v, 1);
EXPECT_TRUE(rawQueryInt(path, "SELECT dcC1DCDistributionPanelCircuitBreaker FROM disLowMainBusCmd", v)); EXPECT_EQ(v, 1);
EXPECT_TRUE(rawQueryInt(path, "SELECT unit2CircuitBreaker FROM disLowBusCmd", v)); EXPECT_EQ(v, 1);
std::remove(path.c_str());
}
TEST(SqliteTest, MultipleInsertsCount)
{
std::string path = tmpPath("multi");
{
SQLite db(path); ASSERT_TRUE(db.createTable());
ccuState c{}; c.ins_soc = 10;
EXPECT_TRUE(db.insertData(c));
EXPECT_TRUE(db.insertData(c));
EXPECT_TRUE(db.insertData(c));
}
long long n = 0;
EXPECT_TRUE(rawCount(path, "ccuState", n));
EXPECT_EQ(n, 3);
std::remove(path.c_str());
}
TEST(SqliteTest, InsertCcuSetParmCmdReadBack)
{
std::string path = tmpPath("setparmcmd");
{
SQLite db(path); ASSERT_TRUE(db.createTable());
ccuSetParmCmd c{}; c.insSocHold1 = 7; c.powerSocHold2 = 88;
EXPECT_TRUE(db.insertData(c));
}
long long v = 0;
EXPECT_TRUE(rawQueryInt(path, "SELECT insSocHold1 FROM ccuSetParmCmd", v));
EXPECT_EQ(v, 7);
EXPECT_TRUE(rawQueryInt(path, "SELECT powerSocHold2 FROM ccuSetParmCmd", v));
EXPECT_EQ(v, 88);
std::remove(path.c_str());
}
TEST(SqliteTest, InsertCcuSetParmFbReadBack)
{
std::string path = tmpPath("setparmfb");
{
SQLite db(path); ASSERT_TRUE(db.createTable());
msg_CcuSetParmFbMsg fb{}; fb.flag = 1; fb.failureCode = 2;
EXPECT_TRUE(db.insertData(fb));
}
long long v = 0;
EXPECT_TRUE(rawQueryInt(path, "SELECT flag FROM ccuSetParmFb", v));
EXPECT_EQ(v, 1);
EXPECT_TRUE(rawQueryInt(path, "SELECT failureCode FROM ccuSetParmFb", v));
EXPECT_EQ(v, 2);
std::remove(path.c_str());
}
TEST(SqliteTest, LogRawFrameReadBack)
{
std::string path = tmpPath("raw");
{
SQLite db(path); ASSERT_TRUE(db.createTable());
const unsigned char frame[] = {0x20, 0x20, 0x51, 0x00, 0x01, 0x02, 0x03};
db.onFrame(0, 0x0051, "ccuState", frame, sizeof(frame), true);
db.onFrame(1, 0x0001, "disHighVolBusCmd", frame, sizeof(frame), true);
}
long long n = 0;
EXPECT_TRUE(rawCount(path, "msg_log", n));
EXPECT_EQ(n, 2);
std::string hex;
EXPECT_TRUE(rawQueryText(path, "SELECT payload_hex FROM msg_log ORDER BY id LIMIT 1", hex));
EXPECT_EQ(hex, "20205100010203");
long long dir = 0;
EXPECT_TRUE(rawQueryInt(path, "SELECT direction FROM msg_log ORDER BY id DESC LIMIT 1", dir));
EXPECT_EQ(dir, 1);
std::remove(path.c_str());
}
TEST(SqliteTest, InvalidPathIsFailOpen)
{
SQLite db("/invalid/path/nonexistent_dir/test.db");
EXPECT_EQ(db.status(), SQLite::Status::Disabled);
EXPECT_FALSE(db.isConnected());
ccuState c{}; c.ins_soc = 1;
EXPECT_FALSE(db.insertData(c)); // 不抛异常,返回 false
ccuColCmd cmd{};
EXPECT_FALSE(db.insertData(cmd));
const unsigned char frame[] = {0x20, 0x20};
db.onFrame(0, 0x0051, "ccuState", frame, sizeof(frame), true); // 不崩溃
}
TEST(SqliteTest, CorruptDatabaseRecovered)
{
std::string path = tmpPath("corrupt");
{
// 写入非 SQLite 内容,模拟损坏的库文件
FILE* f = fopen(path.c_str(), "wb");
ASSERT_TRUE(f != nullptr);
for (int i = 0; i < 4096; ++i) fputc((i * 7 + 3) & 0xFF, f);
fclose(f);
SQLite db(path);
// 应能备份损坏文件并重建,恢复可用
EXPECT_EQ(db.status(), SQLite::Status::OK);
EXPECT_TRUE(db.isConnected());
ccuState c{}; c.ins_soc = 99;
EXPECT_TRUE(db.insertData(c));
}
long long v = 0;
EXPECT_TRUE(rawQueryInt(path, "SELECT ins_soc FROM ccuState", v));
EXPECT_EQ(v, 99);
std::remove(path.c_str());
std::remove((path + ".corrupt").c_str());
}