#include "plugins/protocols/modbus_rtu/codec/ModbusRtuCodec.h" #include #include #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(adu.constData()), static_cast(adu.size()), out, nullptr)); const auto* back = std::get_if(&out); QVERIFY(back); QCOMPARE(static_cast(back->unitId), 1); QCOMPARE(static_cast(back->startAddress), 40001); QCOMPARE(static_cast(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(adu.constData()), static_cast(adu.size()), out, nullptr)); const auto* back = std::get_if(&out); QVERIFY(back); QCOMPARE(static_cast(back->startAddress), 0x10); QCOMPARE(static_cast(back->quantity), 8); } void ModbusRtuPduCodecTest::roundTrip_readCoilsResponse() { ReadCoilsResponse resp; resp.unitId = 0x01; resp.coils = QVector{0x55, 0x01}; QByteArray adu; QVERIFY(encodeModbusRtu(ModbusRtuPdu{resp}, adu, nullptr)); ModbusRtuPdu out; QVERIFY(decodeModbusRtu(BusDirection::Upstream, reinterpret_cast(adu.constData()), static_cast(adu.size()), out, nullptr)); const auto* back = std::get_if(&out); QVERIFY(back); QCOMPARE(back->coils.size(), 2); QCOMPARE(static_cast(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(adu.constData()), static_cast(adu.size()), out, nullptr)); const auto* back = std::get_if(&out); QVERIFY(back); QCOMPARE(static_cast(back->startAddress), 0x20); QCOMPARE(static_cast(back->quantity), 16); } void ModbusRtuPduCodecTest::roundTrip_readDiscreteInputsResponse() { ReadDiscreteInputsResponse resp; resp.unitId = 0x01; resp.discreteInputs = QVector{0x0F}; QByteArray adu; QVERIFY(encodeModbusRtu(ModbusRtuPdu{resp}, adu, nullptr)); ModbusRtuPdu out; QVERIFY(decodeModbusRtu(BusDirection::Upstream, reinterpret_cast(adu.constData()), static_cast(adu.size()), out, nullptr)); const auto* back = std::get_if(&out); QVERIFY(back); QCOMPARE(back->discreteInputs.size(), 1); QCOMPARE(static_cast(back->discreteInputs[0]), 0x0F); } void ModbusRtuPduCodecTest::roundTrip_readHoldingRegistersResponse() { ReadHoldingRegistersResponse resp; resp.unitId = 0x02; resp.registers = QVector{0x00FF, 0x1388}; QByteArray adu; QVERIFY(encodeModbusRtu(ModbusRtuPdu{resp}, adu, nullptr)); ModbusRtuPdu out; QVERIFY(decodeModbusRtu(BusDirection::Upstream, reinterpret_cast(adu.constData()), static_cast(adu.size()), out, nullptr)); const auto* back = std::get_if(&out); QVERIFY(back); QCOMPARE(static_cast(back->unitId), 2); QCOMPARE(back->registers.size(), 2); QCOMPARE(static_cast(back->registers[0]), 255); QCOMPARE(static_cast(back->registers[1]), 5000); } void ModbusRtuPduCodecTest::roundTrip_exception() { const ModbusExceptionPdu ex{0x05, static_cast(0x83), 0x02}; QByteArray adu; QVERIFY(encodeModbusRtu(ModbusRtuPdu{ex}, adu, nullptr)); QCOMPARE(adu.size(), 5); ModbusRtuPdu out; QVERIFY(decodeModbusRtu(BusDirection::Upstream, reinterpret_cast(adu.constData()), static_cast(adu.size()), out, nullptr)); const auto* back = std::get_if(&out); QVERIFY(back); QCOMPARE(static_cast(back->unitId), 5); QCOMPARE(static_cast(back->function), 0x83); QCOMPARE(static_cast(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(aduReq.constData()), static_cast(aduReq.size()), asReq, nullptr)); QVERIFY(std::holds_alternative(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(aduResp.constData()), static_cast(aduResp.size()), asResp, nullptr)); QVERIFY(std::holds_alternative(asResp)); } QTEST_MAIN(ModbusRtuPduCodecTest) #include "modbus_rtu_pdu_codec_test.moc"