modbus rtu
This commit is contained in:
206
tests/modbus_rtu_pdu_codec_test.cpp
Normal file
206
tests/modbus_rtu_pdu_codec_test.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
#include "message_bus/pipeline/protocol/modbusrtu/ModbusRtuCodec.h"
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
|
||||
using softbus::message_bus::pipeline::BusDirection;
|
||||
using softbus::message_bus::pipeline::protocol::ModbusExceptionPdu;
|
||||
using softbus::message_bus::pipeline::protocol::ModbusRtuPdu;
|
||||
using softbus::message_bus::pipeline::protocol::ReadCoilsRequest;
|
||||
using softbus::message_bus::pipeline::protocol::ReadCoilsResponse;
|
||||
using softbus::message_bus::pipeline::protocol::ReadDiscreteInputsRequest;
|
||||
using softbus::message_bus::pipeline::protocol::ReadDiscreteInputsResponse;
|
||||
using softbus::message_bus::pipeline::protocol::ReadHoldingRegistersRequest;
|
||||
using softbus::message_bus::pipeline::protocol::ReadHoldingRegistersResponse;
|
||||
using softbus::message_bus::pipeline::protocol::decodeModbusRtu;
|
||||
using softbus::message_bus::pipeline::protocol::encodeModbusRtu;
|
||||
|
||||
class ModbusRtuPduCodecTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void roundTrip_readCoilsRequest();
|
||||
void roundTrip_readCoilsResponse();
|
||||
void roundTrip_readDiscreteInputsRequest();
|
||||
void roundTrip_readDiscreteInputsResponse();
|
||||
void roundTrip_readHoldingRegistersRequest();
|
||||
void roundTrip_readHoldingRegistersResponse();
|
||||
void roundTrip_exception();
|
||||
void unknownDirection_heuristic_request_vs_response();
|
||||
};
|
||||
|
||||
void ModbusRtuPduCodecTest::roundTrip_readHoldingRegistersRequest()
|
||||
{
|
||||
const ReadHoldingRegistersRequest req{0x01, 40001, 4};
|
||||
QByteArray adu;
|
||||
QVERIFY(encodeModbusRtu(ModbusRtuPdu{req}, adu, nullptr));
|
||||
QCOMPARE(adu.size(), 8);
|
||||
|
||||
ModbusRtuPdu out;
|
||||
QVERIFY(decodeModbusRtu(BusDirection::Downstream,
|
||||
reinterpret_cast<const std::uint8_t*>(adu.constData()),
|
||||
static_cast<std::size_t>(adu.size()),
|
||||
out,
|
||||
nullptr));
|
||||
const auto* back = std::get_if<ReadHoldingRegistersRequest>(&out);
|
||||
QVERIFY(back);
|
||||
QCOMPARE(static_cast<int>(back->unitId), 1);
|
||||
QCOMPARE(static_cast<int>(back->startAddress), 40001);
|
||||
QCOMPARE(static_cast<int>(back->quantity), 4);
|
||||
}
|
||||
|
||||
void ModbusRtuPduCodecTest::roundTrip_readCoilsRequest()
|
||||
{
|
||||
const ReadCoilsRequest req{0x01, 0x0010, 8};
|
||||
QByteArray adu;
|
||||
QVERIFY(encodeModbusRtu(ModbusRtuPdu{req}, adu, nullptr));
|
||||
QCOMPARE(adu.size(), 8);
|
||||
|
||||
ModbusRtuPdu out;
|
||||
QVERIFY(decodeModbusRtu(BusDirection::Downstream,
|
||||
reinterpret_cast<const std::uint8_t*>(adu.constData()),
|
||||
static_cast<std::size_t>(adu.size()),
|
||||
out,
|
||||
nullptr));
|
||||
const auto* back = std::get_if<ReadCoilsRequest>(&out);
|
||||
QVERIFY(back);
|
||||
QCOMPARE(static_cast<int>(back->startAddress), 0x10);
|
||||
QCOMPARE(static_cast<int>(back->quantity), 8);
|
||||
}
|
||||
|
||||
void ModbusRtuPduCodecTest::roundTrip_readCoilsResponse()
|
||||
{
|
||||
ReadCoilsResponse resp;
|
||||
resp.unitId = 0x01;
|
||||
resp.coils = QVector<std::uint8_t>{0x55, 0x01};
|
||||
QByteArray adu;
|
||||
QVERIFY(encodeModbusRtu(ModbusRtuPdu{resp}, adu, nullptr));
|
||||
|
||||
ModbusRtuPdu out;
|
||||
QVERIFY(decodeModbusRtu(BusDirection::Upstream,
|
||||
reinterpret_cast<const std::uint8_t*>(adu.constData()),
|
||||
static_cast<std::size_t>(adu.size()),
|
||||
out,
|
||||
nullptr));
|
||||
const auto* back = std::get_if<ReadCoilsResponse>(&out);
|
||||
QVERIFY(back);
|
||||
QCOMPARE(back->coils.size(), 2);
|
||||
QCOMPARE(static_cast<int>(back->coils[0]), 0x55);
|
||||
}
|
||||
|
||||
void ModbusRtuPduCodecTest::roundTrip_readDiscreteInputsRequest()
|
||||
{
|
||||
const ReadDiscreteInputsRequest req{0x01, 0x0020, 16};
|
||||
QByteArray adu;
|
||||
QVERIFY(encodeModbusRtu(ModbusRtuPdu{req}, adu, nullptr));
|
||||
|
||||
ModbusRtuPdu out;
|
||||
QVERIFY(decodeModbusRtu(BusDirection::Downstream,
|
||||
reinterpret_cast<const std::uint8_t*>(adu.constData()),
|
||||
static_cast<std::size_t>(adu.size()),
|
||||
out,
|
||||
nullptr));
|
||||
const auto* back = std::get_if<ReadDiscreteInputsRequest>(&out);
|
||||
QVERIFY(back);
|
||||
QCOMPARE(static_cast<int>(back->startAddress), 0x20);
|
||||
QCOMPARE(static_cast<int>(back->quantity), 16);
|
||||
}
|
||||
|
||||
void ModbusRtuPduCodecTest::roundTrip_readDiscreteInputsResponse()
|
||||
{
|
||||
ReadDiscreteInputsResponse resp;
|
||||
resp.unitId = 0x01;
|
||||
resp.discreteInputs = QVector<std::uint8_t>{0x0F};
|
||||
QByteArray adu;
|
||||
QVERIFY(encodeModbusRtu(ModbusRtuPdu{resp}, adu, nullptr));
|
||||
|
||||
ModbusRtuPdu out;
|
||||
QVERIFY(decodeModbusRtu(BusDirection::Upstream,
|
||||
reinterpret_cast<const std::uint8_t*>(adu.constData()),
|
||||
static_cast<std::size_t>(adu.size()),
|
||||
out,
|
||||
nullptr));
|
||||
const auto* back = std::get_if<ReadDiscreteInputsResponse>(&out);
|
||||
QVERIFY(back);
|
||||
QCOMPARE(back->discreteInputs.size(), 1);
|
||||
QCOMPARE(static_cast<int>(back->discreteInputs[0]), 0x0F);
|
||||
}
|
||||
|
||||
void ModbusRtuPduCodecTest::roundTrip_readHoldingRegistersResponse()
|
||||
{
|
||||
ReadHoldingRegistersResponse resp;
|
||||
resp.unitId = 0x02;
|
||||
resp.registers = QVector<std::uint16_t>{0x00FF, 0x1388};
|
||||
|
||||
QByteArray adu;
|
||||
QVERIFY(encodeModbusRtu(ModbusRtuPdu{resp}, adu, nullptr));
|
||||
|
||||
ModbusRtuPdu out;
|
||||
QVERIFY(decodeModbusRtu(BusDirection::Upstream,
|
||||
reinterpret_cast<const std::uint8_t*>(adu.constData()),
|
||||
static_cast<std::size_t>(adu.size()),
|
||||
out,
|
||||
nullptr));
|
||||
const auto* back = std::get_if<ReadHoldingRegistersResponse>(&out);
|
||||
QVERIFY(back);
|
||||
QCOMPARE(static_cast<int>(back->unitId), 2);
|
||||
QCOMPARE(back->registers.size(), 2);
|
||||
QCOMPARE(static_cast<int>(back->registers[0]), 255);
|
||||
QCOMPARE(static_cast<int>(back->registers[1]), 5000);
|
||||
}
|
||||
|
||||
void ModbusRtuPduCodecTest::roundTrip_exception()
|
||||
{
|
||||
const ModbusExceptionPdu ex{0x05, static_cast<std::uint8_t>(0x83), 0x02};
|
||||
QByteArray adu;
|
||||
QVERIFY(encodeModbusRtu(ModbusRtuPdu{ex}, adu, nullptr));
|
||||
QCOMPARE(adu.size(), 5);
|
||||
|
||||
ModbusRtuPdu out;
|
||||
QVERIFY(decodeModbusRtu(BusDirection::Upstream,
|
||||
reinterpret_cast<const std::uint8_t*>(adu.constData()),
|
||||
static_cast<std::size_t>(adu.size()),
|
||||
out,
|
||||
nullptr));
|
||||
const auto* back = std::get_if<ModbusExceptionPdu>(&out);
|
||||
QVERIFY(back);
|
||||
QCOMPARE(static_cast<int>(back->unitId), 5);
|
||||
QCOMPARE(static_cast<int>(back->function), 0x83);
|
||||
QCOMPARE(static_cast<int>(back->exceptionCode), 2);
|
||||
}
|
||||
|
||||
void ModbusRtuPduCodecTest::unknownDirection_heuristic_request_vs_response()
|
||||
{
|
||||
ReadHoldingRegistersRequest req{0x01, 0, 1};
|
||||
QByteArray aduReq;
|
||||
QVERIFY(encodeModbusRtu(ModbusRtuPdu{req}, aduReq, nullptr));
|
||||
|
||||
ModbusRtuPdu asReq;
|
||||
QVERIFY(decodeModbusRtu(BusDirection::Unknown,
|
||||
reinterpret_cast<const std::uint8_t*>(aduReq.constData()),
|
||||
static_cast<std::size_t>(aduReq.size()),
|
||||
asReq,
|
||||
nullptr));
|
||||
QVERIFY(std::holds_alternative<ReadHoldingRegistersRequest>(asReq));
|
||||
|
||||
ReadHoldingRegistersResponse resp;
|
||||
resp.unitId = 1;
|
||||
resp.registers = {0x00AA};
|
||||
QByteArray aduResp;
|
||||
QVERIFY(encodeModbusRtu(ModbusRtuPdu{resp}, aduResp, nullptr));
|
||||
|
||||
ModbusRtuPdu asResp;
|
||||
QVERIFY(decodeModbusRtu(BusDirection::Unknown,
|
||||
reinterpret_cast<const std::uint8_t*>(aduResp.constData()),
|
||||
static_cast<std::size_t>(aduResp.size()),
|
||||
asResp,
|
||||
nullptr));
|
||||
QVERIFY(std::holds_alternative<ReadHoldingRegistersResponse>(asResp));
|
||||
}
|
||||
|
||||
QTEST_MAIN(ModbusRtuPduCodecTest)
|
||||
#include "modbus_rtu_pdu_codec_test.moc"
|
||||
Reference in New Issue
Block a user