372 lines
12 KiB
C++
372 lines
12 KiB
C++
|
|
#include "app.hpp"
|
|||
|
|
#include <cassert>
|
|||
|
|
#include <iostream>
|
|||
|
|
#include <vector>
|
|||
|
|
#include <cmath>
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 测试基础通用通信单元 (SU-COM) 的接口初始化功能。
|
|||
|
|
*
|
|||
|
|
* @requirement(name="基础通用通讯功能", id="SRS-F-01-001")
|
|||
|
|
* 验证以太网、RS422、CAN、模拟量、离散量接口初始化正确性。
|
|||
|
|
*/
|
|||
|
|
static void test_su_com_communication() {
|
|||
|
|
std::cout << "[TEST] SU-COM: 基础通用通信测试...\n";
|
|||
|
|
|
|||
|
|
// 以太网:有效参数应返回 true
|
|||
|
|
assert(bntvs::initEthernetComm("192.168.1.1", 8080) == true);
|
|||
|
|
// 空 IP 应返回 false
|
|||
|
|
assert(bntvs::initEthernetComm("", 8080) == false);
|
|||
|
|
|
|||
|
|
// RS422:有效参数应返回 true
|
|||
|
|
assert(bntvs::initRS422Comm("COM1", 115200) == true);
|
|||
|
|
// 波特率过低应返回 false
|
|||
|
|
assert(bntvs::initRS422Comm("COM1", 100) == false);
|
|||
|
|
|
|||
|
|
// CAN:有效参数应返回 true
|
|||
|
|
assert(bntvs::initCANComm("can0", 250000) == true);
|
|||
|
|
// 波特率超范围应返回 false
|
|||
|
|
assert(bntvs::initCANComm("can0", 2000000) == false);
|
|||
|
|
|
|||
|
|
// 模拟量:应返回 true
|
|||
|
|
assert(bntvs::initAnalogComm(0) == true);
|
|||
|
|
|
|||
|
|
// 离散量:有效引脚应返回 true
|
|||
|
|
assert(bntvs::initDigitalComm(0) == true);
|
|||
|
|
// 引脚超范围应返回 false
|
|||
|
|
assert(bntvs::initDigitalComm(48) == false);
|
|||
|
|
|
|||
|
|
std::cout << " PASS\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 测试协议兼容单元 (SU-PROT) 的协议识别与转换功能。
|
|||
|
|
*
|
|||
|
|
* @requirement(name="协议兼容功能", id="SRS-F-01-002")
|
|||
|
|
* 验证 CAN2.0 与 CAN FD 协议的自动识别和兼容转换。
|
|||
|
|
*/
|
|||
|
|
static void test_su_prot_protocol_compat() {
|
|||
|
|
std::cout << "[TEST] SU-PROT: 协议兼容测试...\n";
|
|||
|
|
|
|||
|
|
// CAN2.0 帧(≤8 字节)
|
|||
|
|
std::vector<uint8_t> can20_data = {0x11, 0x22, 0x33, 0x44};
|
|||
|
|
assert(bntvs::detectCANProtocol(can20_data) == bntvs::CANProtocolType::CAN2_0);
|
|||
|
|
|
|||
|
|
// CAN FD 帧(>8 字节)
|
|||
|
|
std::vector<uint8_t> canfd_data(32, 0x55);
|
|||
|
|
assert(bntvs::detectCANProtocol(canfd_data) == bntvs::CANProtocolType::CANFD);
|
|||
|
|
|
|||
|
|
// CAN FD → CAN 2.0 转换
|
|||
|
|
auto result = bntvs::convertCANFrame(
|
|||
|
|
bntvs::CANProtocolType::CANFD,
|
|||
|
|
bntvs::CANProtocolType::CAN2_0,
|
|||
|
|
canfd_data);
|
|||
|
|
assert(result.size() == 8); // 截断到 8 字节
|
|||
|
|
|
|||
|
|
// CAN 2.0 → CAN FD 转换(相同协议不应改变)
|
|||
|
|
result = bntvs::convertCANFrame(
|
|||
|
|
bntvs::CANProtocolType::CAN2_0,
|
|||
|
|
bntvs::CANProtocolType::CAN2_0,
|
|||
|
|
can20_data);
|
|||
|
|
assert(result.size() == can20_data.size());
|
|||
|
|
|
|||
|
|
std::cout << " PASS\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 测试数据存储单元 (SU-STOR) 的功能。
|
|||
|
|
*
|
|||
|
|
* @requirement(name="数据存储功能", id="SRS-F-02-001")
|
|||
|
|
* 验证数据持久化存储及存储服务生命周期管理。
|
|||
|
|
*/
|
|||
|
|
static void test_su_stor_data_storage() {
|
|||
|
|
std::cout << "[TEST] SU-STOR: 数据存储测试...\n";
|
|||
|
|
|
|||
|
|
// 存储服务未启动时,存储应失败
|
|||
|
|
bntvs::BusDataRecord record;
|
|||
|
|
record.bus_type = "CAN";
|
|||
|
|
record.frame_id = 0x100;
|
|||
|
|
record.data_content = {0x01, 0x02};
|
|||
|
|
record.data_length = 2;
|
|||
|
|
assert(bntvs::storeBusData(record) == false);
|
|||
|
|
|
|||
|
|
// 启动存储服务后,存储应成功
|
|||
|
|
assert(bntvs::startStorageService() == true);
|
|||
|
|
assert(bntvs::storeBusData(record) == true);
|
|||
|
|
|
|||
|
|
// 重复启动不应失败
|
|||
|
|
assert(bntvs::startStorageService() == true);
|
|||
|
|
|
|||
|
|
// 停止存储服务
|
|||
|
|
assert(bntvs::stopStorageService() == true);
|
|||
|
|
|
|||
|
|
std::cout << " PASS\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 测试数据管理与回放单元 (SU-REPLAY) 的功能。
|
|||
|
|
*
|
|||
|
|
* @requirement(name="数据管理与数据回放功能", id="SRS-F-02-002")
|
|||
|
|
* 验证数据查询、回放和删除功能。
|
|||
|
|
*/
|
|||
|
|
static void test_su_replay_data_management() {
|
|||
|
|
std::cout << "[TEST] SU-REPLAY: 数据管理与回放测试...\n";
|
|||
|
|
|
|||
|
|
// 查询(返回空列表)
|
|||
|
|
auto results = bntvs::queryBusData("CAN", "2024-01-01", "2024-12-31");
|
|||
|
|
assert(results.empty());
|
|||
|
|
|
|||
|
|
// 回放
|
|||
|
|
bntvs::BusDataRecord record;
|
|||
|
|
uint64_t callback_count = 0;
|
|||
|
|
uint64_t replayed = bntvs::replayBusData(
|
|||
|
|
{record, record, record}, 2.0,
|
|||
|
|
[&callback_count](const bntvs::BusDataRecord&) { ++callback_count; });
|
|||
|
|
assert(replayed == 3);
|
|||
|
|
assert(callback_count == 3);
|
|||
|
|
|
|||
|
|
// 删除
|
|||
|
|
assert(bntvs::deleteBusData(1) == true);
|
|||
|
|
assert(bntvs::deleteBusData(0) == false);
|
|||
|
|
|
|||
|
|
std::cout << " PASS\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 测试信号转换单元 (SU-CONV) 的功能。
|
|||
|
|
*
|
|||
|
|
* @requirement(name="信号转换功能", id="SRS-F-06-001")
|
|||
|
|
* @requirement(name="模拟量离散量转总线信号功能", id="SRS-F-06-005")
|
|||
|
|
* 验证模拟量和离散量到总线信号的转换。
|
|||
|
|
*/
|
|||
|
|
static void test_su_conv_signal_conversion() {
|
|||
|
|
std::cout << "[TEST] SU-CONV: 信号转换测试...\n";
|
|||
|
|
|
|||
|
|
// 模拟量转换:0V → 应编码为 0
|
|||
|
|
auto result = bntvs::convertAnalogToBus(0.0, 0x100);
|
|||
|
|
assert(result.frame_id == 0x100);
|
|||
|
|
assert(result.bus_type == "CAN");
|
|||
|
|
assert(!result.data_content.empty());
|
|||
|
|
|
|||
|
|
// 模拟量转换:10V → 应编码为 4095 (12-bit)
|
|||
|
|
result = bntvs::convertAnalogToBus(10.0, 0x200);
|
|||
|
|
assert(result.data_content.size() == 2);
|
|||
|
|
|
|||
|
|
// 离散量转换:高电平
|
|||
|
|
result = bntvs::convertDigitalToBus(5, 0x300);
|
|||
|
|
assert(result.data_content[0] == 1);
|
|||
|
|
|
|||
|
|
// 离散量转换:低电平
|
|||
|
|
result = bntvs::convertDigitalToBus(0, 0x301);
|
|||
|
|
assert(result.data_content[0] == 0);
|
|||
|
|
|
|||
|
|
std::cout << " PASS\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 测试总线路由单元 (SU-ROUTE) 的功能。
|
|||
|
|
*
|
|||
|
|
* @requirement(name="数据转发交换功能", id="SRS-F-07-001")
|
|||
|
|
* @requirement(name="路由寻址功能", id="SRS-F-07-002")
|
|||
|
|
* @requirement(name="以太网-CAN协议转换适配功能", id="SRS-F-07-003")
|
|||
|
|
* @requirement(name="路由功能要求", id="SRS-F-07-007")
|
|||
|
|
* 验证路由转发、协议转换和路由表管理。
|
|||
|
|
*/
|
|||
|
|
static void test_su_route_routing() {
|
|||
|
|
std::cout << "[TEST] SU-ROUTE: 总线路由测试...\n";
|
|||
|
|
|
|||
|
|
bntvs::BusDataRecord frame;
|
|||
|
|
frame.frame_id = 0x100;
|
|||
|
|
|
|||
|
|
// 路由表为空时转发应失败
|
|||
|
|
assert(bntvs::routeDataFrame(frame) == false);
|
|||
|
|
|
|||
|
|
// 添加静态路由
|
|||
|
|
bntvs::RouteEntry route;
|
|||
|
|
route.dest_network = "192.168.2.0";
|
|||
|
|
route.netmask = "255.255.255.0";
|
|||
|
|
route.next_hop = "192.168.1.1";
|
|||
|
|
route.out_interface = "eth0";
|
|||
|
|
route.priority = 10;
|
|||
|
|
assert(bntvs::addStaticRoute(route) == true);
|
|||
|
|
|
|||
|
|
// 添加动态路由
|
|||
|
|
route.dest_network = "192.168.3.0";
|
|||
|
|
route.next_hop = "192.168.1.2";
|
|||
|
|
assert(bntvs::addDynamicRoute(route) == true);
|
|||
|
|
|
|||
|
|
// 路由转发应成功
|
|||
|
|
assert(bntvs::routeDataFrame(frame) == true);
|
|||
|
|
|
|||
|
|
// 以太网↔CAN 协议转换
|
|||
|
|
auto can_frame = bntvs::convertEthernetToCAN(frame);
|
|||
|
|
assert(can_frame.bus_type == "CAN");
|
|||
|
|
|
|||
|
|
auto eth_frame = bntvs::convertCANToEthernet(can_frame);
|
|||
|
|
assert(eth_frame.bus_type == "ETHERNET");
|
|||
|
|
|
|||
|
|
std::cout << " PASS\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 测试总线分析单元 (SU-ANALY) 的功能。
|
|||
|
|
*
|
|||
|
|
* @requirement(name="总线实时监听功能", id="SRS-F-09-001")
|
|||
|
|
* @requirement(name="协议解析解码功能", id="SRS-F-09-002")
|
|||
|
|
* @requirement(name="故障诊断分析功能", id="SRS-F-09-003")
|
|||
|
|
* @requirement(name="波形与时序分析功能", id="SRS-F-09-004")
|
|||
|
|
* @requirement(name="网络状态监视功能", id="SRS-F-09-006")
|
|||
|
|
* @requirement(name="错误帧识别要求", id="SRS-F-09-011")
|
|||
|
|
* 验证监听、解析、诊断、波形分析和状态监视功能。
|
|||
|
|
*/
|
|||
|
|
static void test_su_analy_bus_analysis() {
|
|||
|
|
std::cout << "[TEST] SU-ANALY: 总线分析测试...\n";
|
|||
|
|
|
|||
|
|
// 监听启动/停止
|
|||
|
|
bool cb_called = false;
|
|||
|
|
assert(bntvs::startBusMonitoring(bntvs::BusType::CAN,
|
|||
|
|
[&cb_called](const bntvs::BusDataRecord&) { cb_called = true; }) == true);
|
|||
|
|
assert(bntvs::stopBusMonitoring() == true);
|
|||
|
|
|
|||
|
|
// 协议解析
|
|||
|
|
std::vector<uint8_t> raw = {0x00, 0x00, 0x01, 0x23, 0xAA, 0xBB};
|
|||
|
|
auto parsed = bntvs::parseCANFrame(raw);
|
|||
|
|
assert(parsed.frame_id == 0x00000123);
|
|||
|
|
assert(parsed.protocol_type == "CAN2.0");
|
|||
|
|
|
|||
|
|
// CAN FD 解析(>8 字节数据,但帧头仍为4字节)
|
|||
|
|
std::vector<uint8_t> raw_fd(20, 0x11);
|
|||
|
|
raw_fd[0] = 0x00; raw_fd[1] = 0x00; raw_fd[2] = 0x01; raw_fd[3] = 0xFF;
|
|||
|
|
auto parsed_fd = bntvs::parseCANFrame(raw_fd);
|
|||
|
|
assert(parsed_fd.protocol_type == "CANFD");
|
|||
|
|
|
|||
|
|
// 故障诊断:正常数据
|
|||
|
|
bntvs::BusDataRecord normal_frame;
|
|||
|
|
normal_frame.data_content = {0x01, 0x02, 0x03};
|
|||
|
|
assert(bntvs::diagnoseBusFault(normal_frame) == "");
|
|||
|
|
|
|||
|
|
// 故障诊断:CRC 错误(首字节为 0xFF)
|
|||
|
|
bntvs::BusDataRecord crc_error_frame;
|
|||
|
|
crc_error_frame.data_content = {0xFF, 0x00};
|
|||
|
|
assert(!bntvs::diagnoseBusFault(crc_error_frame).empty());
|
|||
|
|
|
|||
|
|
// 错误帧检测
|
|||
|
|
std::vector<uint8_t> bad_data = {0xFF, 0x01};
|
|||
|
|
assert(bntvs::checkErrorFrame(bad_data) == true);
|
|||
|
|
std::vector<uint8_t> good_data = {0x01, 0x02};
|
|||
|
|
assert(bntvs::checkErrorFrame(good_data) == false);
|
|||
|
|
|
|||
|
|
// 波形分析
|
|||
|
|
std::vector<double> sine;
|
|||
|
|
for (int i = 0; i < 100; ++i) {
|
|||
|
|
sine.push_back(std::sin(2.0 * 3.14159 * 10.0 * i / 100.0));
|
|||
|
|
}
|
|||
|
|
auto wf = bntvs::analyzeWaveform(sine, 1000.0);
|
|||
|
|
assert(!wf.analysis_summary.empty());
|
|||
|
|
assert(wf.signal_frequency_hz > 0);
|
|||
|
|
|
|||
|
|
// 网络状态
|
|||
|
|
auto status = bntvs::getNetworkStatus(bntvs::BusType::CAN);
|
|||
|
|
assert(!status.last_update_time.empty());
|
|||
|
|
|
|||
|
|
std::cout << " PASS\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 测试故障注入单元 (SU-FAULT) 的功能。
|
|||
|
|
*
|
|||
|
|
* @requirement(name="总线短路/断路注入", id="SRS-F-12-001")
|
|||
|
|
* @requirement(name="电磁干扰注入", id="SRS-F-12-002")
|
|||
|
|
* @requirement(name="错误帧注入", id="SRS-F-12-003")
|
|||
|
|
* @requirement(name="节点离线/异常接入", id="SRS-F-12-004")
|
|||
|
|
* @requirement(name="波特率异常波动注入", id="SRS-F-12-005")
|
|||
|
|
* 验证各类故障注入功能。
|
|||
|
|
*/
|
|||
|
|
static void test_su_fault_fault_injection() {
|
|||
|
|
std::cout << "[TEST] SU-FAULT: 故障注入测试...\n";
|
|||
|
|
|
|||
|
|
assert(bntvs::injectShortCircuit(bntvs::BusType::CAN, 100) == true);
|
|||
|
|
assert(bntvs::injectOpenCircuit(bntvs::BusType::ETHERNET, 200) == true);
|
|||
|
|
|
|||
|
|
// 有效强度 (0.0~1.0)
|
|||
|
|
assert(bntvs::injectEMI(bntvs::BusType::CAN, 0.5, 100) == true);
|
|||
|
|
// 无效强度应失败
|
|||
|
|
assert(bntvs::injectEMI(bntvs::BusType::CAN, 1.5, 100) == false);
|
|||
|
|
|
|||
|
|
assert(bntvs::injectErrorFrame(bntvs::BusType::CAN, "CRC错误") == true);
|
|||
|
|
assert(bntvs::injectNodeOffline("NODE_A", 500) == true);
|
|||
|
|
assert(bntvs::injectNodeAbnormal("NODE_B") == true);
|
|||
|
|
assert(bntvs::injectBaudRateAnomaly(bntvs::BusType::CAN, 50000, 300) == true);
|
|||
|
|
|
|||
|
|
std::cout << " PASS\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 测试总线测试分析单元 (SU-TEST) 的功能。
|
|||
|
|
*
|
|||
|
|
* @requirement(name="40m内总线测试分析功能", id="SRS-F-10-001")
|
|||
|
|
* @requirement(name="40m以上总线测试分析功能", id="SRS-F-10-002")
|
|||
|
|
* @requirement(name="长时间满负荷测试分析功能", id="SRS-F-10-003")
|
|||
|
|
* 验证各类总线性能测试功能。
|
|||
|
|
*/
|
|||
|
|
static void test_su_test_bus_testing() {
|
|||
|
|
std::cout << "[TEST] SU-TEST: 总线测试分析测试...\n";
|
|||
|
|
|
|||
|
|
auto short_result = bntvs::testShortBusPerformance(bntvs::BusType::CAN, 10);
|
|||
|
|
assert(short_result.avg_latency_us > 0);
|
|||
|
|
assert(short_result.throughput_mbps > 0);
|
|||
|
|
|
|||
|
|
auto long_result = bntvs::testLongBusPerformance(bntvs::BusType::CAN, 10);
|
|||
|
|
assert(long_result.avg_latency_us > 0);
|
|||
|
|
|
|||
|
|
auto stress_result = bntvs::testLongDurationStability(bntvs::BusType::CAN, 24);
|
|||
|
|
assert(stress_result.total_packets > 0);
|
|||
|
|
assert(stress_result.total_packets >= stress_result.lost_packets);
|
|||
|
|
|
|||
|
|
// 长距离延迟应大于短距离
|
|||
|
|
assert(long_result.avg_latency_us >= short_result.avg_latency_us);
|
|||
|
|
|
|||
|
|
std::cout << " PASS\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 测试辅助函数。
|
|||
|
|
*/
|
|||
|
|
static void test_utilities() {
|
|||
|
|
std::cout << "[TEST] 辅助函数测试...\n";
|
|||
|
|
|
|||
|
|
auto version = bntvs::getVersion();
|
|||
|
|
assert(!version.empty());
|
|||
|
|
assert(version.find("BNTVS_SW") != std::string::npos);
|
|||
|
|
|
|||
|
|
// printHelp 仅输出,不返回值,但不应崩溃
|
|||
|
|
bntvs::printHelp();
|
|||
|
|
|
|||
|
|
std::cout << " PASS\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 主测试函数,汇总所有测试用例。
|
|||
|
|
*/
|
|||
|
|
int main() {
|
|||
|
|
std::cout << "========================================\n";
|
|||
|
|
std::cout << " BNTVS_SW 单元测试\n";
|
|||
|
|
std::cout << "========================================\n\n";
|
|||
|
|
|
|||
|
|
test_su_com_communication();
|
|||
|
|
test_su_prot_protocol_compat();
|
|||
|
|
test_su_stor_data_storage();
|
|||
|
|
test_su_replay_data_management();
|
|||
|
|
test_su_conv_signal_conversion();
|
|||
|
|
test_su_route_routing();
|
|||
|
|
test_su_analy_bus_analysis();
|
|||
|
|
test_su_fault_fault_injection();
|
|||
|
|
test_su_test_bus_testing();
|
|||
|
|
test_utilities();
|
|||
|
|
|
|||
|
|
std::cout << "\n========================================\n";
|
|||
|
|
std::cout << " 全部测试通过!\n";
|
|||
|
|
std::cout << "========================================\n";
|
|||
|
|
return 0;
|
|||
|
|
}
|