1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtSerialBus module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include <private/qmodbusadu_p.h>
38
39#include <QtTest/QtTest>
40
41class tst_QModbusAdu : public QObject
42{
43 Q_OBJECT
44
45private slots:
46 void testQByteArrayConstructor()
47 {
48 QModbusSerialAdu adu(QModbusSerialAdu::Ascii, ":f0010300120008f2\r\n");
49 QCOMPARE(adu.size(), 7);
50 QCOMPARE(adu.data(), QByteArray::fromHex("f0010300120008"));
51
52 QCOMPARE(adu.rawSize(), 19);
53 QCOMPARE(adu.rawData(), QByteArray(":f0010300120008f2\r\n"));
54
55 adu = QModbusSerialAdu(QModbusSerialAdu::Rtu, QByteArray::fromHex(hexEncoded: "f00103001200080f1d"));
56 QCOMPARE(adu.size(), 7);
57 QCOMPARE(adu.data(), QByteArray::fromHex("f0010300120008"));
58
59 QCOMPARE(adu.rawSize(), 9);
60 QCOMPARE(adu.rawData(), QByteArray::fromHex("f00103001200080f1d"));
61 }
62
63 void testSlaveAddress()
64 {
65 QModbusSerialAdu adu(QModbusSerialAdu::Ascii, ":f0010300120008f2\r\n");
66 QCOMPARE(adu.serverAddress(), 240);
67
68 adu = QModbusSerialAdu(QModbusSerialAdu::Rtu, QByteArray::fromHex(hexEncoded: "f00103001200080f1d"));
69 QCOMPARE(adu.serverAddress(), 240);
70 }
71
72 void testPdu()
73 {
74 QModbusSerialAdu adu(QModbusSerialAdu::Ascii, ":f0010300120008f2\r\n");
75 QCOMPARE(adu.pdu().functionCode(), QModbusPdu::ReadCoils);
76 QCOMPARE(adu.pdu().data(), QByteArray::fromHex("0300120008"));
77
78 adu = QModbusSerialAdu(QModbusSerialAdu::Rtu, QByteArray::fromHex(hexEncoded: "f00103001200080f1d"));
79 QCOMPARE(adu.pdu().functionCode(), QModbusPdu::ReadCoils);
80 QCOMPARE(adu.pdu().data(), QByteArray::fromHex("0300120008"));
81 }
82
83 void testChecksum()
84 {
85 QModbusSerialAdu adu(QModbusSerialAdu::Ascii, ":f0010300120008f2\r\n");
86 QCOMPARE(adu.checksum<quint8>(), quint8(0xf2));
87
88 adu = QModbusSerialAdu(QModbusSerialAdu::Rtu, QByteArray::fromHex(hexEncoded: "f00103001200080f1d"));
89 QCOMPARE(adu.checksum<quint16>(), quint16(0x0f1d));
90 }
91
92 void testMatchingChecksum()
93 {
94 QModbusSerialAdu adu(QModbusSerialAdu::Ascii, ":f0010300120008f2\r\n");
95 QCOMPARE(adu.matchingChecksum(), true);
96
97 adu = QModbusSerialAdu(QModbusSerialAdu::Rtu, QByteArray::fromHex(hexEncoded: "f00103001200080f1d"));
98 QCOMPARE(adu.matchingChecksum(), true);
99 }
100
101 void testCreate()
102 {
103 const QModbusRequest pdu(QModbusPdu::ReadHoldingRegisters, QByteArray::fromHex(hexEncoded: "006B0003"));
104
105 QModbusSerialAdu adu(QModbusSerialAdu::Ascii, ":1103006b00037e\r\n");
106 QByteArray ba = QModbusSerialAdu::create(type: QModbusSerialAdu::Ascii, serverAddress: 17, pdu);
107 QCOMPARE(adu.rawData(), ba);
108 QCOMPARE(adu.data(), QModbusSerialAdu(QModbusSerialAdu::Ascii, ba).data());
109
110 adu = QModbusSerialAdu(QModbusSerialAdu::Rtu, QByteArray::fromHex(hexEncoded: "1103006b00037687"));
111 ba = QModbusSerialAdu::create(type: QModbusSerialAdu::Rtu, serverAddress: 17, pdu);
112 QCOMPARE(ba, adu.rawData());
113 QCOMPARE(adu.data(), QModbusSerialAdu(QModbusSerialAdu::Rtu, ba).data());
114 }
115
116 void testChecksumLRC_data()
117 {
118 // Modbus ASCII Messages generated with pymodbus message-generator.py
119
120 QTest::addColumn<QByteArray>(name: "pdu");
121 QTest::addColumn<quint8>(name: "lrc");
122
123 QTest::newRow(dataTag: ":0107F8")
124 << QByteArray::fromHex(hexEncoded: "0107")
125 << quint8(0xF8);
126 QTest::newRow(dataTag: ":010BF4")
127 << QByteArray::fromHex(hexEncoded: "010B")
128 << quint8(0xF4);
129 QTest::newRow(dataTag: ":010CF3")
130 << QByteArray::fromHex(hexEncoded: "010C")
131 << quint8(0xF3);
132 QTest::newRow(dataTag: ":0111EE")
133 << QByteArray::fromHex(hexEncoded: "0111")
134 << quint8(0xEE);
135 QTest::newRow(dataTag: ":011400EB")
136 << QByteArray::fromHex(hexEncoded: "011400")
137 << quint8(0xEB);
138 QTest::newRow(dataTag: ":011500EA")
139 << QByteArray::fromHex(hexEncoded: "011500")
140 << quint8(0xEA);
141 QTest::newRow(dataTag: ":1103006B00037E")
142 << QByteArray::fromHex(hexEncoded: "1103006B0003")
143 << quint8(0x7E);
144 QTest::newRow(dataTag: ":01160012FFFF0000D9")
145 << QByteArray::fromHex(hexEncoded: "01160012FFFF0000")
146 << quint8(0xD9);
147 QTest::newRow(dataTag: ":0110001200081000010001000100010001000100010001BD")
148 << QByteArray::fromHex(hexEncoded: "0110001200081000010001000100010001000100010001")
149 << quint8(0xBD);
150 QTest::newRow(dataTag: ":011700120008000000081000010001000100010001000100010001AE")
151 << QByteArray::fromHex(hexEncoded: "011700120008000000081000010001000100010001000100010001")
152 << quint8(0xAE);
153
154 }
155 void testChecksumLRC()
156 {
157 QFETCH(QByteArray, pdu);
158 QFETCH(quint8, lrc);
159 QCOMPARE(QModbusSerialAdu::calculateLRC(pdu.constData(), pdu.size()), lrc);
160 }
161
162 void testChecksumCRC_data()
163 {
164 // Modbus RTU Messages generated with pymodbus message-generator.py
165
166 QTest::addColumn<QByteArray>(name: "pdu");
167 QTest::addColumn<quint16>(name: "crc");
168
169 QTest::newRow(dataTag: "010300120008e409") << QByteArray::fromHex(hexEncoded: "010300120008") << quint16(0xe409);
170 QTest::newRow(dataTag: "010200120008d9c9") << QByteArray::fromHex(hexEncoded: "010200120008") << quint16(0xd9c9);
171 QTest::newRow(dataTag: "01040012000851c9") << QByteArray::fromHex(hexEncoded: "010400120008") << quint16(0x51c9);
172 QTest::newRow(dataTag: "0101001200089dc9") << QByteArray::fromHex(hexEncoded: "010100120008") << quint16(0x9dc9);
173 QTest::newRow(dataTag: "010f0012000801ff06d6") << QByteArray::fromHex(hexEncoded: "010f0012000801ff")
174 << quint16(0x06d6);
175 QTest::newRow(dataTag: "0110001200081000010001000100010001000100010001d551")
176 << QByteArray::fromHex(hexEncoded: "0110001200081000010001000100010001000100010001")
177 << quint16(0xd551);
178 QTest::newRow(dataTag: "010600120001e80f") << QByteArray::fromHex(hexEncoded: "010600120001") << quint16(0xe80f);
179 QTest::newRow(dataTag: "01050012ff002c3f") << QByteArray::fromHex(hexEncoded: "01050012ff00") << quint16(0x2c3f);
180 QTest::newRow(dataTag: "011700120008000000081000010001000100010001000100010001e6f8")
181 << QByteArray::fromHex(hexEncoded: "011700120008000000081000010001000100010001000100010001")
182 << quint16(0xe6f8);
183 QTest::newRow(dataTag: "010741e2") << QByteArray::fromHex(hexEncoded: "0107") << quint16(0x41e2);
184 QTest::newRow(dataTag: "010b41e7") << QByteArray::fromHex(hexEncoded: "010b") << quint16(0x41e7);
185 QTest::newRow(dataTag: "010c0025") << QByteArray::fromHex(hexEncoded: "010c") << quint16(0x0025);
186 QTest::newRow(dataTag: "0111c02c") << QByteArray::fromHex(hexEncoded: "0111") << quint16(0xc02c);
187 QTest::newRow(dataTag: "0114002f00") << QByteArray::fromHex(hexEncoded: "011400") << quint16(0x2f00);
188 QTest::newRow(dataTag: "0115002e90") << QByteArray::fromHex(hexEncoded: "011500") << quint16(0x2e90);
189 QTest::newRow(dataTag: "01160012ffff00004e21") << QByteArray::fromHex(hexEncoded: "01160012ffff0000")
190 << quint16(0x4e21);
191 QTest::newRow(dataTag: "0118001201d2") << QByteArray::fromHex(hexEncoded: "01180012") << quint16(0x01d2);
192 QTest::newRow(dataTag: "012b0e01007077") << QByteArray::fromHex(hexEncoded: "012b0e0100") << quint16(0x7077);
193 QTest::newRow(dataTag: "010800000000e00b") << QByteArray::fromHex(hexEncoded: "010800000000") << quint16(0xe00b);
194 QTest::newRow(dataTag: "010800010000b1cb") << QByteArray::fromHex(hexEncoded: "010800010000") << quint16(0xb1cb);
195 QTest::newRow(dataTag: "01080002000041cb") << QByteArray::fromHex(hexEncoded: "010800020000") << quint16(0x41cb);
196 QTest::newRow(dataTag: "010800030000100b") << QByteArray::fromHex(hexEncoded: "010800030000") << quint16(0x100b);
197 QTest::newRow(dataTag: "010800040000a1ca") << QByteArray::fromHex(hexEncoded: "010800040000") << quint16(0xa1ca);
198 QTest::newRow(dataTag: "0108000a0000c009") << QByteArray::fromHex(hexEncoded: "0108000a0000") << quint16(0xc009);
199 QTest::newRow(dataTag: "0108000b000091c9") << QByteArray::fromHex(hexEncoded: "0108000b0000") << quint16(0x91c9);
200 QTest::newRow(dataTag: "0108000c00002008") << QByteArray::fromHex(hexEncoded: "0108000c0000") << quint16(0x2008);
201 QTest::newRow(dataTag: "0108000d000071c8") << QByteArray::fromHex(hexEncoded: "0108000d0000") << quint16(0x71c8);
202 QTest::newRow(dataTag: "0108000e000081c8") << QByteArray::fromHex(hexEncoded: "0108000e0000") << quint16(0x81c8);
203 QTest::newRow(dataTag: "0108000f0000d008") << QByteArray::fromHex(hexEncoded: "0108000f0000") << quint16(0xd008);
204 QTest::newRow(dataTag: "010800100000e1ce") << QByteArray::fromHex(hexEncoded: "010800100000") << quint16(0xe1ce);
205 QTest::newRow(dataTag: "010800110000b00e") << QByteArray::fromHex(hexEncoded: "010800110000") << quint16(0xb00e);
206 QTest::newRow(dataTag: "010800120000400e") << QByteArray::fromHex(hexEncoded: "010800120000") << quint16(0x400e);
207 QTest::newRow(dataTag: "01080013000011ce") << QByteArray::fromHex(hexEncoded: "010800130000") << quint16(0x11ce);
208 QTest::newRow(dataTag: "010800140000a00f") << QByteArray::fromHex(hexEncoded: "010800140000") << quint16(0xa00f);
209 QTest::newRow(dataTag: "010800150000f1cf") << QByteArray::fromHex(hexEncoded: "010800150000") << quint16(0xf1cf);
210 }
211
212 void testChecksumCRC()
213 {
214 QFETCH(QByteArray, pdu);
215 QFETCH(quint16, crc);
216 QCOMPARE(QModbusSerialAdu::calculateCRC(pdu.constData(), pdu.size()), crc);
217 }
218};
219
220QTEST_MAIN(tst_QModbusAdu)
221
222#include "tst_qmodbusadu.moc"
223

source code of qtserialbus/tests/auto/qmodbusadu/tst_qmodbusadu.cpp