document_generate/tests/basic_test.cpp

372 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}