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 <QtCore/qdebug.h>
38#include <QtSerialBus/qmodbuspdu.h>
39
40#include <QtTest/QtTest>
41
42static QString s_msg;
43static void myMessageHandler(QtMsgType, const QMessageLogContext &, const QString &msg)
44{
45 s_msg = msg;
46}
47
48class DebugHandler
49{
50public:
51 DebugHandler(QtMessageHandler newMessageHandler)
52 : oldMessageHandler(qInstallMessageHandler(newMessageHandler)) {}
53 ~DebugHandler() {
54 qInstallMessageHandler(oldMessageHandler);
55 }
56private:
57 QtMessageHandler oldMessageHandler;
58};
59
60static int minimumDataSize(const QModbusPdu &pdu, bool request)
61{
62 if (pdu.isException())
63 return 1;
64
65 switch (pdu.functionCode()) {
66 case QModbusPdu::ReadCoils:
67 case QModbusPdu::ReadDiscreteInputs:
68 return request ? 4 : 2;
69 case QModbusPdu::WriteSingleCoil:
70 case QModbusPdu::WriteSingleRegister:
71 return 4;
72 case QModbusPdu::ReadHoldingRegisters:
73 case QModbusPdu::ReadInputRegisters:
74 return request ? 4 : 3;
75 case QModbusPdu::ReadExceptionStatus:
76 return request ? 0 : 1;
77 case QModbusPdu::Diagnostics:
78 return 4;
79 case QModbusPdu::GetCommEventCounter:
80 return request ? 0 : 4;
81 case QModbusPdu::GetCommEventLog:
82 return request ? 0 : 8;
83 case QModbusPdu::WriteMultipleCoils:
84 return request ? 6 : 4;
85 case QModbusPdu::WriteMultipleRegisters:
86 return request ? 7 : 4;
87 case QModbusPdu::ReportServerId:
88 return request ? 0 : 3;
89 case QModbusPdu::ReadFileRecord:
90 return request ? 8 : 5;
91 case QModbusPdu::WriteFileRecord:
92 return 10;
93 case QModbusPdu::MaskWriteRegister:
94 return 6;
95 case QModbusPdu::ReadWriteMultipleRegisters:
96 return request ? 11 : 3;
97 case QModbusPdu::ReadFifoQueue:
98 return request ? 2 : 6;
99 case QModbusPdu::EncapsulatedInterfaceTransport:
100 return 2;
101 case QModbusPdu::Invalid:
102 case QModbusPdu::UndefinedFunctionCode:
103 return -1;
104 }
105 return -1;
106}
107
108class tst_QModbusPdu : public QObject
109{
110 Q_OBJECT
111
112private slots:
113 void testDefaultConstructor()
114 {
115 QModbusRequest request;
116 QCOMPARE(request.isValid(), false);
117 QCOMPARE(request.isException(), false);
118 QCOMPARE(request.functionCode(), QModbusRequest::FunctionCode(0x00));
119 QCOMPARE(request.exceptionCode(), QModbusPdu::ExtendedException);
120 QCOMPARE(request.data().toHex(), QByteArray());
121
122 QModbusResponse response;
123 QCOMPARE(response.isValid(), false);
124 QCOMPARE(response.isException(), false);
125 QCOMPARE(response.functionCode(), QModbusResponse::FunctionCode(0x00));
126 QCOMPARE(response.exceptionCode(), QModbusPdu::ExtendedException);
127 QCOMPARE(response.data().toHex(), QByteArray());
128
129 QModbusExceptionResponse exception;
130 QCOMPARE(exception.isValid(), false);
131 QCOMPARE(exception.isException(), false);
132 QCOMPARE(exception.exceptionCode(), QModbusPdu::ExtendedException);
133 QCOMPARE(exception.functionCode(), QModbusExceptionResponse::FunctionCode(0x00));
134 QCOMPARE(exception.data().toHex(), QByteArray());
135 }
136
137 void testVaridicConstructor()
138 {
139 QModbusRequest request(QModbusRequest::ReportServerId);
140 QCOMPARE(request.isValid(), true);
141 QCOMPARE(request.isException(), false);
142 QCOMPARE(request.functionCode(), QModbusRequest::ReportServerId);
143 QCOMPARE(request.exceptionCode(), QModbusPdu::ExtendedException);
144 QCOMPARE(request.data().toHex(), QByteArray());
145
146 // Byte Count, Server ID, Run Indicator Status
147 QModbusResponse response(QModbusResponse::ReportServerId, quint8(0x02), quint8(0x01),
148 quint8(0xff));
149 QCOMPARE(response.isValid(), true);
150 QCOMPARE(response.isException(), false);
151 QCOMPARE(response.functionCode(), QModbusResponse::ReportServerId);
152 QCOMPARE(response.exceptionCode(), QModbusPdu::ExtendedException);
153 QCOMPARE(response.data().toHex(), QByteArray("0201ff"));
154 }
155
156 void testQByteArrayConstructor()
157 {
158 QModbusRequest request(QModbusRequest::ReportServerId, QByteArray());
159 QCOMPARE(request.isValid(), true);
160 QCOMPARE(request.isException(), false);
161 QCOMPARE(request.functionCode(), QModbusRequest::ReportServerId);
162 QCOMPARE(request.data().toHex(), QByteArray());
163
164 // Byte Count, Server ID, Run Indicator Status
165 QModbusResponse response(QModbusResponse::ReportServerId, QByteArray::fromHex(hexEncoded: "ff0102"));
166 QCOMPARE(response.isValid(), true);
167 QCOMPARE(response.isException(), false);
168 QCOMPARE(response.functionCode(), QModbusResponse::ReportServerId);
169 QCOMPARE(response.data().toHex(), QByteArray("ff0102"));
170 }
171
172 void testCopyConstructorAndAssignment()
173 {
174 QModbusPdu pdu;
175 pdu.setFunctionCode(QModbusPdu::ReadCoils);
176
177 QModbusRequest request(pdu);
178 QCOMPARE(request.functionCode(), QModbusResponse::ReadCoils);
179
180 QModbusResponse response(pdu);
181 QCOMPARE(response.functionCode(), QModbusResponse::ReadCoils);
182
183 pdu.setFunctionCode(QModbusPdu::WriteMultipleCoils);
184
185 request = pdu;
186 QCOMPARE(request.functionCode(), QModbusResponse::WriteMultipleCoils);
187
188 response = pdu;
189 QCOMPARE(response.functionCode(), QModbusResponse::WriteMultipleCoils);
190 }
191
192 void testEncodeDecode()
193 {
194 QModbusRequest invalid;
195 quint8 data = 0xff;
196 invalid.decodeData(newData: &data);
197 QCOMPARE(data, quint8(0xff));
198 invalid.encodeData(newData: data);
199 QCOMPARE(invalid.data().toHex(), QByteArray("ff"));
200
201 data = 0x00;
202 QModbusRequest request(QModbusRequest::ReportServerId);
203 request.decodeData(newData: &data);
204 QCOMPARE(data, quint8(0x00));
205 QCOMPARE(request.data().toHex(), QByteArray());
206
207 QModbusResponse response(QModbusResponse::ReportServerId);
208 response.encodeData(newData: quint8(0x02), newData: quint8(0x01), newData: quint8(0xff));
209 quint8 count = 0, id = 0, run = 0;
210 response.decodeData(newData: &count, newData: &id, newData: &run);
211 QCOMPARE(count, quint8(0x02));
212 QCOMPARE(id, quint8(0x01));
213 QCOMPARE(run, quint8(0xff));
214 QCOMPARE(response.data().toHex(), QByteArray("0201ff"));
215
216 count = 0, id = 0, run = 0;
217 response = QModbusResponse(QModbusResponse::ReportServerId, QByteArray::fromHex(hexEncoded: "0201ff"));
218 QCOMPARE(response.isValid(), true);
219 QCOMPARE(response.isException(), false);
220 QCOMPARE(response.functionCode(), QModbusResponse::ReportServerId);
221 QCOMPARE(response.data().toHex(), QByteArray("0201ff"));
222 response.decodeData(newData: &count, newData: &id, newData: &run);
223 QCOMPARE(count, quint8(0x02));
224 QCOMPARE(id, quint8(0x01));
225 QCOMPARE(run, quint8(0xff));
226
227 QModbusRequest readCoils(QModbusRequest::ReadCoils);
228 // starting address and quantity of coils
229 readCoils.encodeData(newData: quint16(12), newData: quint16(10));
230 quint16 address, quantity;
231 readCoils.decodeData(newData: &address, newData: &quantity);
232 QCOMPARE(address, quint16(0x0c));
233 QCOMPARE(quantity, quint16(0x0a));
234
235 request = QModbusRequest(QModbusRequest::WriteMultipleCoils,
236 QByteArray::fromHex(hexEncoded: "0013000a02cd01"));
237 QCOMPARE(request.data().toHex(), QByteArray("0013000a02cd01"));
238 address = 0xffff, quantity = 0xffff;
239 quint8 bytes = 0xff, firstByte = 0xff, secondByte = 0xff;
240 request.decodeData(newData: &address, newData: &quantity, newData: &bytes, newData: &firstByte, newData: &secondByte);
241 QCOMPARE(address, quint16(19));
242 QCOMPARE(quantity, quint16(10));
243 QCOMPARE(bytes, quint8(2));
244 QCOMPARE(firstByte, quint8(0xcd));
245 QCOMPARE(secondByte, quint8(0x01));
246 }
247
248 void testQModbusExceptionResponsePdu()
249 {
250 QModbusExceptionResponse exception(QModbusExceptionResponse::ReportServerId,
251 QModbusExceptionResponse::ServerDeviceFailure);
252 QCOMPARE(exception.isValid(), true);
253 QCOMPARE(exception.isException(), true);
254 QCOMPARE(exception.functionCode(), QModbusExceptionResponse::ReportServerId);
255 QCOMPARE(exception.data().toHex(), QByteArray("04"));
256 QCOMPARE(exception.exceptionCode(), QModbusExceptionResponse::ServerDeviceFailure);
257
258 QModbusExceptionResponse response;
259 QCOMPARE(response.isValid(), false);
260 QCOMPARE(response.isException(), false);
261 QCOMPARE(response.functionCode(), QModbusExceptionResponse::Invalid);
262
263 response.setFunctionCode(QModbusExceptionResponse::ReportServerId);
264 response.setExceptionCode(QModbusExceptionResponse::ServerDeviceFailure);
265 QCOMPARE(response.isValid(), true);
266 QCOMPARE(response.isException(), true);
267 QCOMPARE(response.functionCode(), QModbusExceptionResponse::ReportServerId);
268 QCOMPARE(response.data().toHex(), QByteArray("04"));
269 QCOMPARE(exception.exceptionCode(), QModbusExceptionResponse::ServerDeviceFailure);
270
271 QModbusPdu pdu;
272 pdu.setFunctionCode(QModbusExceptionResponse::FunctionCode(QModbusPdu::ReadCoils
273 | QModbusPdu::ExceptionByte));
274 QCOMPARE(pdu.isException(), true);
275 QCOMPARE(pdu.functionCode(), QModbusPdu::ReadCoils);
276
277 QModbusExceptionResponse exception2(pdu);
278 QCOMPARE(exception2.isException(), true);
279 QCOMPARE(exception2.functionCode(), QModbusPdu::ReadCoils);
280 QCOMPARE(exception2.exceptionCode(), QModbusExceptionResponse::ExtendedException);
281 exception2.setExceptionCode(QModbusExceptionResponse::IllegalFunction);
282 QCOMPARE(exception2.exceptionCode(), QModbusExceptionResponse::IllegalFunction);
283
284 QModbusExceptionResponse exception3 = pdu;
285 QCOMPARE(exception3.isException(), true);
286 QCOMPARE(exception3.functionCode(), QModbusPdu::ReadCoils);
287 QCOMPARE(exception3.exceptionCode(), QModbusExceptionResponse::ExtendedException);
288 }
289
290 void testQDebugStreamOperator()
291 {
292 DebugHandler mhs(myMessageHandler);
293 {
294 QDebug d = qDebug();
295 d << QModbusPdu();
296 d << QModbusRequest();
297 d << QModbusResponse();
298 d << QModbusExceptionResponse();
299 }
300 QCOMPARE(s_msg, QString::fromLatin1("0x00 0x00 0x00 0x00"));
301
302 {
303 QDebug d = qDebug();
304 d << QModbusRequest(QModbusRequest::ReadCoils, quint16(19), quint16(19));
305 }
306 QCOMPARE(s_msg, QString::fromLatin1("0x0100130013"));
307
308 {
309 QDebug d = qDebug();
310 d << QModbusResponse(QModbusResponse::ReadCoils, QByteArray::fromHex(hexEncoded: "03cd6b05"));
311 }
312 QCOMPARE(s_msg, QString::fromLatin1("0x0103cd6b05"));
313
314 {
315 QDebug d = qDebug();
316 d << QModbusExceptionResponse(QModbusExceptionResponse::ReadCoils,
317 QModbusExceptionResponse::IllegalDataAddress);
318 }
319 QCOMPARE(s_msg, QString::fromLatin1("0x8102"));
320 }
321
322 void testMinimumDataSize()
323 {
324 bool request = true;
325 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadCoils), request),
326 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadCoils)));
327 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadDiscreteInputs), request),
328 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadDiscreteInputs)));
329 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteSingleCoil), request),
330 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::WriteSingleCoil)));
331 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadHoldingRegisters), request),
332 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadHoldingRegisters)));
333 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadInputRegisters), request),
334 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadInputRegisters)));
335 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteSingleRegister), request),
336 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::WriteSingleRegister)));
337 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadExceptionStatus), request),
338 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadExceptionStatus)));
339 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::Diagnostics), request),
340 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::Diagnostics)));
341 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::GetCommEventCounter), request),
342 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::GetCommEventCounter)));
343 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::GetCommEventLog), request),
344 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::GetCommEventLog)));
345 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteMultipleCoils), request),
346 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::WriteMultipleCoils)));
347 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteMultipleRegisters), request),
348 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::WriteMultipleRegisters)));
349 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReportServerId), request),
350 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReportServerId)));
351 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadFileRecord), request),
352 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadFileRecord)));
353 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteFileRecord), request),
354 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::WriteFileRecord)));
355 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::MaskWriteRegister), request),
356 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::MaskWriteRegister)));
357 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadWriteMultipleRegisters), request),
358 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadWriteMultipleRegisters)));
359 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadFifoQueue), request),
360 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::ReadFifoQueue)));
361 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::EncapsulatedInterfaceTransport), request),
362 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::EncapsulatedInterfaceTransport)));
363 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::Invalid), request),
364 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::Invalid)));
365 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::UndefinedFunctionCode), request),
366 QModbusRequest::minimumDataSize(QModbusRequest(QModbusRequest::Invalid)));
367
368 request = false;
369 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadCoils), request),
370 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadCoils)));
371 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadDiscreteInputs), request),
372 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadDiscreteInputs)));
373 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteSingleCoil), request),
374 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::WriteSingleCoil)));
375 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadHoldingRegisters), request),
376 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadHoldingRegisters)));
377 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadInputRegisters), request),
378 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadInputRegisters)));
379 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteSingleRegister), request),
380 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::WriteSingleRegister)));
381 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadExceptionStatus), request),
382 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadExceptionStatus)));
383 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::Diagnostics), request),
384 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::Diagnostics)));
385 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::GetCommEventCounter), request),
386 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::GetCommEventCounter)));
387 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::GetCommEventLog), request),
388 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::GetCommEventLog)));
389 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteMultipleCoils), request),
390 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::WriteMultipleCoils)));
391 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteMultipleRegisters), request),
392 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::WriteMultipleRegisters)));
393 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReportServerId), request),
394 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReportServerId)));
395 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadFileRecord), request),
396 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadFileRecord)));
397 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::WriteFileRecord), request),
398 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::WriteFileRecord)));
399 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::MaskWriteRegister), request),
400 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::MaskWriteRegister)));
401 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadWriteMultipleRegisters), request),
402 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadWriteMultipleRegisters)));
403 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::ReadFifoQueue), request),
404 QModbusResponse::minimumDataSize(QModbusResponse(QModbusResponse::ReadFifoQueue)));
405 QCOMPARE(minimumDataSize(QModbusRequest(QModbusPdu::EncapsulatedInterfaceTransport), request),
406 QModbusResponse::minimumDataSize(QModbusRequest(QModbusPdu::EncapsulatedInterfaceTransport)));
407 QCOMPARE(minimumDataSize(QModbusResponse(QModbusPdu::Invalid), request),
408 QModbusRequest::minimumDataSize(QModbusResponse(QModbusPdu::Invalid)));
409 QCOMPARE(minimumDataSize(QModbusResponse(QModbusPdu::UndefinedFunctionCode), request),
410 QModbusRequest::minimumDataSize(QModbusResponse(QModbusPdu::Invalid)));
411
412 QModbusExceptionResponse exception(QModbusResponse::ReadCoils, QModbusPdu::IllegalFunction);
413 QCOMPARE(minimumDataSize(exception, request), 1);
414 QCOMPARE(QModbusResponse::minimumDataSize(exception), 1);
415 }
416
417 void testQModbusRequestStreamOperator_data()
418 {
419 QTest::addColumn<QModbusPdu::FunctionCode>(name: "fc");
420 QTest::addColumn<QByteArray>(name: "data");
421 QTest::addColumn<QByteArray>(name: "pdu");
422
423 QTest::newRow(dataTag: "ReadCoils") << QModbusRequest::ReadCoils << QByteArray::fromHex(hexEncoded: "00130013")
424 << QByteArray::fromHex(hexEncoded: "0100130013");
425 QTest::newRow(dataTag: "ReadDiscreteInputs") << QModbusRequest::ReadDiscreteInputs
426 << QByteArray::fromHex(hexEncoded: "00c40016") << QByteArray::fromHex(hexEncoded: "0200c40016");
427 QTest::newRow(dataTag: "ReadHoldingRegisters") << QModbusRequest::ReadHoldingRegisters
428 << QByteArray::fromHex(hexEncoded: "006b0003") << QByteArray::fromHex(hexEncoded: "03006b0003");
429 QTest::newRow(dataTag: "ReadInputRegisters") << QModbusRequest::ReadInputRegisters
430 << QByteArray::fromHex(hexEncoded: "00080001") << QByteArray::fromHex(hexEncoded: "0400080001");
431 QTest::newRow(dataTag: "WriteSingleCoil") << QModbusRequest::WriteSingleCoil
432 << QByteArray::fromHex(hexEncoded: "00acff00") << QByteArray::fromHex(hexEncoded: "0500acff00");
433 QTest::newRow(dataTag: "WriteSingleRegister") << QModbusRequest::WriteSingleRegister
434 << QByteArray::fromHex(hexEncoded: "00010003") << QByteArray::fromHex(hexEncoded: "0600010003");
435 QTest::newRow(dataTag: "ReadExceptionStatus") << QModbusRequest::ReadExceptionStatus
436 << QByteArray() << QByteArray::fromHex(hexEncoded: "07");
437 QTest::newRow(dataTag: "Diagnostics") << QModbusRequest::Diagnostics
438 << QByteArray::fromHex(hexEncoded: "0000a537") << QByteArray::fromHex(hexEncoded: "080000a537");
439 QTest::newRow(dataTag: "GetCommEventCounter") << QModbusRequest::GetCommEventCounter
440 << QByteArray() << QByteArray::fromHex(hexEncoded: "0b");
441 QTest::newRow(dataTag: "GetCommEventLog") << QModbusRequest::GetCommEventLog
442 << QByteArray() << QByteArray::fromHex(hexEncoded: "0c");
443 QTest::newRow(dataTag: "WriteMultipleCoils") << QModbusRequest::WriteMultipleCoils
444 << QByteArray::fromHex(hexEncoded: "0013000a02cd01") << QByteArray::fromHex(hexEncoded: "0f0013000a02cd01");
445 QTest::newRow(dataTag: "WriteMultipleRegisters") << QModbusRequest::WriteMultipleRegisters
446 << QByteArray::fromHex(hexEncoded: "0001000204000a0102") << QByteArray::fromHex(hexEncoded: "100001000204000a0102");
447 QTest::newRow(dataTag: "ReportServerId") << QModbusRequest::ReportServerId
448 << QByteArray() << QByteArray::fromHex(hexEncoded: "11");
449 QTest::newRow(dataTag: "ReadFileRecord") << QModbusRequest::ReadFileRecord
450 << QByteArray::fromHex(hexEncoded: "0e0600040001000206000300090002")
451 << QByteArray::fromHex(hexEncoded: "140e0600040001000206000300090002");
452 QTest::newRow(dataTag: "WriteFileRecord") << QModbusRequest::WriteFileRecord
453 << QByteArray::fromHex(hexEncoded: "0d0600040007000306af04be100d")
454 << QByteArray::fromHex(hexEncoded: "150d0600040007000306af04be100d");
455 QTest::newRow(dataTag: "MaskWriteRegister") << QModbusRequest::MaskWriteRegister
456 << QByteArray::fromHex(hexEncoded: "000400f20025") << QByteArray::fromHex(hexEncoded: "16000400f20025");
457 QTest::newRow(dataTag: "ReadWriteMultipleRegisters") << QModbusRequest::ReadWriteMultipleRegisters
458 << QByteArray::fromHex(hexEncoded: "00030006000e00030600ff00ff00ff")
459 << QByteArray::fromHex(hexEncoded: "1700030006000e00030600ff00ff00ff");
460 QTest::newRow(dataTag: "ReadFifoQueue") << QModbusRequest::ReadFifoQueue
461 << QByteArray::fromHex(hexEncoded: "04de") << QByteArray::fromHex(hexEncoded: "1804de");
462 QTest::newRow(dataTag: "EncapsulatedInterfaceTransport")
463 << QModbusRequest::EncapsulatedInterfaceTransport
464 << QByteArray::fromHex(hexEncoded: "0e0100") << QByteArray::fromHex(hexEncoded: "2b0e0100");
465 }
466
467 void testQModbusRequestStreamOperator()
468 {
469 QFETCH(QModbusPdu::FunctionCode, fc);
470 QFETCH(QByteArray, data);
471 QFETCH(QByteArray, pdu);
472
473 QByteArray ba;
474 QDataStream output(&ba, QIODevice::WriteOnly);
475 output << QModbusRequest(fc, data);
476 QCOMPARE(ba, pdu);
477
478 QModbusRequest request;
479 QDataStream input(pdu);
480 input >> request;
481 QCOMPARE(request.functionCode(), fc);
482 QCOMPARE(request.data(), data);
483 }
484
485 void testQModbusResponseStreamOperator_data()
486 {
487 QTest::addColumn<QModbusPdu::FunctionCode>(name: "fc");
488 QTest::addColumn<QByteArray>(name: "data");
489 QTest::addColumn<QByteArray>(name: "pdu");
490
491 QTest::newRow(dataTag: "ReadCoils") << QModbusResponse::ReadCoils << QByteArray::fromHex(hexEncoded: "03cd6b05")
492 << QByteArray::fromHex(hexEncoded: "0103cd6b05");
493 QTest::newRow(dataTag: "ReadDiscreteInputs") << QModbusResponse::ReadDiscreteInputs
494 << QByteArray::fromHex(hexEncoded: "03acdb35") << QByteArray::fromHex(hexEncoded: "0203acdb35");
495 QTest::newRow(dataTag: "ReadHoldingRegisters") << QModbusResponse::ReadHoldingRegisters
496 << QByteArray::fromHex(hexEncoded: "06022b00000064") << QByteArray::fromHex(hexEncoded: "0306022b00000064");
497 QTest::newRow(dataTag: "ReadInputRegisters") << QModbusResponse::ReadInputRegisters
498 << QByteArray::fromHex(hexEncoded: "02000a") << QByteArray::fromHex(hexEncoded: "0402000a");
499 QTest::newRow(dataTag: "WriteSingleCoil") << QModbusResponse::WriteSingleCoil
500 << QByteArray::fromHex(hexEncoded: "00acff00") << QByteArray::fromHex(hexEncoded: "0500acff00");
501 QTest::newRow(dataTag: "WriteSingleRegister") << QModbusResponse::WriteSingleRegister
502 << QByteArray::fromHex(hexEncoded: "00010003") << QByteArray::fromHex(hexEncoded: "0600010003");
503 QTest::newRow(dataTag: "ReadExceptionStatus") << QModbusResponse::ReadExceptionStatus
504 << QByteArray::fromHex(hexEncoded: "6d") << QByteArray::fromHex(hexEncoded: "076d");
505 QTest::newRow(dataTag: "Diagnostics") << QModbusResponse::Diagnostics
506 << QByteArray::fromHex(hexEncoded: "ffff0108") << QByteArray::fromHex(hexEncoded: "08ffff0108");
507 QTest::newRow(dataTag: "GetCommEventCounter") << QModbusResponse::GetCommEventCounter
508 << QByteArray::fromHex(hexEncoded: "ffff0108") << QByteArray::fromHex(hexEncoded: "0bffff0108");
509 QTest::newRow(dataTag: "GetCommEventLog") << QModbusResponse::GetCommEventLog
510 << QByteArray::fromHex(hexEncoded: "080000010801212000") << QByteArray::fromHex(hexEncoded: "0c080000010801212000");
511 QTest::newRow(dataTag: "WriteMultipleCoils") << QModbusResponse::WriteMultipleCoils
512 << QByteArray::fromHex(hexEncoded: "0013000a") << QByteArray::fromHex(hexEncoded: "0f0013000a");
513 QTest::newRow(dataTag: "WriteMultipleRegisters") << QModbusResponse::WriteMultipleRegisters
514 << QByteArray::fromHex(hexEncoded: "00010002") << QByteArray::fromHex(hexEncoded: "1000010002");
515 QTest::newRow(dataTag: "ReportServerId") << QModbusResponse::ReportServerId
516 << QByteArray::fromHex(hexEncoded: "030aff12") << QByteArray::fromHex(hexEncoded: "11030aff12");
517 QTest::newRow(dataTag: "ReadFileRecord") << QModbusResponse::ReadFileRecord
518 << QByteArray::fromHex(hexEncoded: "0c05060dfe0020050633cd0040")
519 << QByteArray::fromHex(hexEncoded: "140c05060dfe0020050633cd0040");
520 QTest::newRow(dataTag: "WriteFileRecord") << QModbusResponse::WriteFileRecord
521 << QByteArray::fromHex(hexEncoded: "0d0600040007000306af04be100d")
522 << QByteArray::fromHex(hexEncoded: "150d0600040007000306af04be100d");
523 QTest::newRow(dataTag: "MaskWriteRegister") << QModbusResponse::MaskWriteRegister
524 << QByteArray::fromHex(hexEncoded: "000400f20025") << QByteArray::fromHex(hexEncoded: "16000400f20025");
525 QTest::newRow(dataTag: "ReadWriteMultipleRegisters") << QModbusResponse::ReadWriteMultipleRegisters
526 << QByteArray::fromHex(hexEncoded: "0c00fe0acd00010003000d00ff")
527 << QByteArray::fromHex(hexEncoded: "170c00fe0acd00010003000d00ff");
528 QTest::newRow(dataTag: "ReadFifoQueue") << QModbusResponse::ReadFifoQueue
529 << QByteArray::fromHex(hexEncoded: "0006000201b81284") << QByteArray::fromHex(hexEncoded: "180006000201b81284");
530 QTest::newRow(dataTag: "EncapsulatedInterfaceTransport")
531 << QModbusResponse::EncapsulatedInterfaceTransport
532 << QByteArray::fromHex(hexEncoded: "0e01010000030016") + "Company identification" +
533 QByteArray::fromHex(hexEncoded: "010c") + "Product code" + QByteArray::fromHex(hexEncoded: "0205") +
534 "V2.11"
535 << QByteArray::fromHex(hexEncoded: "2b0e01010000030016") + "Company identification" +
536 QByteArray::fromHex(hexEncoded: "010c") + "Product code" + QByteArray::fromHex(hexEncoded: "0205") +
537 "V2.11";
538
539 QModbusExceptionResponse ex(QModbusPdu::ReadCoils, QModbusPdu::IllegalDataAddress);
540 QTest::newRow(dataTag: "StreamExceptionResponse")
541 << QModbusPdu::FunctionCode(ex.functionCode() | QModbusPdu::ExceptionByte)
542 << QByteArray::fromHex(hexEncoded: "02") << QByteArray::fromHex(hexEncoded: "8102");
543 }
544
545 void testQModbusResponseStreamOperator()
546 {
547 QFETCH(QModbusPdu::FunctionCode, fc);
548 QFETCH(QByteArray, data);
549 QFETCH(QByteArray, pdu);
550
551 QByteArray ba;
552 QDataStream output(&ba, QIODevice::WriteOnly);
553 output << QModbusResponse(fc, data);
554 QCOMPARE(ba, pdu);
555
556 QModbusResponse response;
557 QDataStream input(pdu);
558 input >> response;
559 if (response.isException())
560 QCOMPARE(quint8(response.functionCode()), quint8(fc &~ QModbusPdu::ExceptionByte));
561 else
562 QCOMPARE(response.functionCode(), fc);
563 QCOMPARE(response.data(), data);
564 }
565
566 void testEncapsulatedInterfaceTransportStreamOperator()
567 {
568 const QByteArray valid = QByteArray::fromHex(hexEncoded: "0e01010000030016") + "Company identification"
569 + QByteArray::fromHex(hexEncoded: "010c") + "Product code" + QByteArray::fromHex(hexEncoded: "0205")
570 + "V2.11";
571 {
572 QByteArray ba;
573 QDataStream output(&ba, QIODevice::ReadWrite);
574 output << QModbusResponse(QModbusResponse::EncapsulatedInterfaceTransport, valid);
575
576 QModbusResponse response;
577 QDataStream input(ba);
578 input >> response;
579 QCOMPARE(response.functionCode(), QModbusResponse::EncapsulatedInterfaceTransport);
580 QCOMPARE(response.data(), valid);
581 }
582
583 // valid embedded
584 const QByteArray suffix = QByteArray::fromHex(hexEncoded: "ffffffffff");
585 {
586 QByteArray ba;
587 QDataStream output(&ba, QIODevice::ReadWrite);
588 output << QModbusResponse(QModbusResponse::EncapsulatedInterfaceTransport, valid
589 + suffix);
590
591 QModbusResponse response;
592 QDataStream input(ba);
593 input >> response;
594 QCOMPARE(response.functionCode(), QModbusResponse::EncapsulatedInterfaceTransport);
595 QCOMPARE(response.data(), valid);
596 }
597
598 const QByteArray invalid = QByteArray::fromHex(hexEncoded: "0e01010000030016") + "Company identification"
599 + QByteArray::fromHex(hexEncoded: "01ff") + "Product code" + QByteArray::fromHex(hexEncoded: "0205")
600 + "V2.11";
601 {
602 QByteArray ba;
603 QDataStream output(&ba, QIODevice::ReadWrite);
604 output << QModbusResponse(QModbusResponse::EncapsulatedInterfaceTransport, invalid);
605
606 QModbusResponse response;
607 QDataStream input(ba);
608 input >> response;
609 QCOMPARE(response.functionCode(), QModbusResponse::Invalid);
610 QCOMPARE(response.data(), QByteArray());
611 }
612
613 const QByteArray invalidShort = QByteArray::fromHex(hexEncoded: "0e01010000030016")
614 + "Company identification" + QByteArray::fromHex(hexEncoded: "01");
615 {
616 QByteArray ba;
617 QDataStream output(&ba, QIODevice::ReadWrite);
618 output << QModbusResponse(QModbusResponse::EncapsulatedInterfaceTransport, invalidShort);
619
620 QModbusResponse response;
621 QDataStream input(ba);
622 input >> response;
623 QCOMPARE(response.functionCode(), QModbusResponse::Invalid);
624 QCOMPARE(response.data(), QByteArray());
625 }
626 }
627
628 void testCalculateDataSize()
629 {
630 // CanOpenGeneralReference
631 QModbusResponse cogr(QModbusPdu::EncapsulatedInterfaceTransport, quint8(0x0d));
632 QCOMPARE(QModbusResponse::calculateDataSize(cogr), -1);
633 cogr.encodeData(newData: quint8(0x0d), newData: quint8(0x00));
634 QCOMPARE(QModbusResponse::calculateDataSize(cogr), 2);
635 // TODO: fix the following once we can calculate the size for CanOpenGeneralReference
636 cogr.encodeData(newData: quint8(0x0d), newData: quint8(0x00), newData: quint8(0x00));
637 QCOMPARE(QModbusResponse::calculateDataSize(cogr), 2);
638
639 // ReadDeviceIdentification
640 QModbusResponse rdi(QModbusPdu::EncapsulatedInterfaceTransport, quint8(0x0e));
641 QCOMPARE(QModbusResponse::calculateDataSize(rdi), -1);
642 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01));
643 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8);
644 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01));
645 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8);
646 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00));
647 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8);
648 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00));
649 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8);
650
651 // single object
652 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
653 newData: quint8(0x01)); // object count
654 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8);
655 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
656 newData: quint8(0x01),
657 newData: quint8(0x00)); // object id
658 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8);
659 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
660 newData: quint8(0x01),
661 newData: quint8(0x00), newData: quint8(0x01)); // object size
662 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 9);
663 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
664 newData: quint8(0x01),
665 newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff)); // object data
666 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 9);
667 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
668 newData: quint8(0x01),
669 newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff),
670 newData: quint8(0xff)); // dummy additional data
671 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 9);
672
673 // multiple objects equal size
674 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff), newData: quint8(0x02),
675 newData: quint8(0x02)); // object count
676 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8);
677 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff), newData: quint8(0x02),
678 newData: quint8(0x02),
679 newData: quint8(0x00)); // object id
680 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8);
681 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
682 newData: quint8(0x02),
683 newData: quint8(0x00), newData: quint8(0x01)); // object size
684 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 11);
685 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
686 newData: quint8(0x02),
687 newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff)); // object data
688 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 11);
689 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
690 newData: quint8(0x02),
691 newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff),
692 newData: quint8(0x01)); // second object id
693 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 11);
694 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
695 newData: quint8(0x02),
696 newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff),
697 newData: quint8(0x01), newData: quint8(0x01)); // second object size
698 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 12);
699 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
700 newData: quint8(0x02),
701 newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff),
702 newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff)); // second object data
703 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 12);
704 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
705 newData: quint8(0x02),
706 newData: quint8(0x00), newData: quint8(0x01), newData: quint8(0xff),
707 newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff),
708 newData: quint8(0xff)); // dummy additional data
709 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 12);
710
711 // multiple objects different size
712 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff), newData: quint8(0x02),
713 newData: quint8(0x03));
714 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8);
715 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0xff), newData: quint8(0x02),
716 newData: quint8(0x03),
717 newData: quint8(0x00));
718 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 8);
719 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
720 newData: quint8(0x03),
721 newData: quint8(0x00), newData: quint8(0x01));
722 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 13);
723 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
724 newData: quint8(0x03),
725 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff));
726 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 14);
727 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
728 newData: quint8(0x03),
729 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff));
730 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 14);
731 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
732 newData: quint8(0x03),
733 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
734 newData: quint8(0x01));
735 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 14);
736 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
737 newData: quint8(0x03),
738 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
739 newData: quint8(0x01), newData: quint8(0x03));
740 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 14);
741 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
742 newData: quint8(0x03),
743 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
744 newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff));
745 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 14);
746 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
747 newData: quint8(0x03),
748 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
749 newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff));
750 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 17);
751 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
752 newData: quint8(0x03),
753 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
754 newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff));
755 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 17);
756 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
757 newData: quint8(0x03),
758 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
759 newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff),
760 newData: quint8(0x02));
761 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 17);
762 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
763 newData: quint8(0x03),
764 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
765 newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff),
766 newData: quint8(0x02), newData: quint8(0x05));
767 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22);
768 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
769 newData: quint8(0x03),
770 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
771 newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff),
772 newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff));
773 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22);
774 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
775 newData: quint8(0x03),
776 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
777 newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff),
778 newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff), newData: quint8(0xff));
779 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22);
780 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
781 newData: quint8(0x03),
782 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
783 newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff),
784 newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff));
785 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22);
786 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
787 newData: quint8(0x03),
788 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
789 newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff),
790 newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff));
791 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22);
792 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
793 newData: quint8(0x03),
794 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
795 newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff),
796 newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff));
797 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22);
798 rdi.encodeData(newData: quint8(0x0e), newData: quint8(0x01), newData: quint8(0x01), newData: quint8(0x00), newData: quint8(0x00),
799 newData: quint8(0x03),
800 newData: quint8(0x00), newData: quint8(0x02), newData: quint8(0xff), newData: quint8(0xff),
801 newData: quint8(0x01), newData: quint8(0x03), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff),
802 newData: quint8(0x02), newData: quint8(0x05), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff), newData: quint8(0xff),
803 newData: quint8(0xff)); // dummy additional data
804 QCOMPARE(QModbusResponse::calculateDataSize(rdi), 22);
805 }
806
807 void testCustomCalculator()
808 {
809 // request
810 QModbusRequest request(QModbusRequest::WriteSingleCoil);
811 request.encodeData(newData: quint8(0x00), newData: quint8(0xac), newData: quint8(0xff), newData: quint8(0x00));
812 QCOMPARE(QModbusRequest::calculateDataSize(request), 4);
813
814 QModbusRequest::registerDataSizeCalculator(fc: QModbusRequest::WriteSingleCoil,
815 func: [](const QModbusRequest &)->int {
816 return 15;
817 });
818 QCOMPARE(QModbusRequest::calculateDataSize(request), 15);
819
820 QModbusRequest::registerDataSizeCalculator(fc: QModbusRequest::WriteSingleCoil, func: nullptr);
821 QCOMPARE(QModbusRequest::calculateDataSize(request), 4);
822
823 // response
824 QModbusResponse response(QModbusRequest::WriteSingleCoil);
825 response.encodeData(newData: quint8(0x00), newData: quint8(0xac), newData: quint8(0xff), newData: quint8(0x00));
826 QCOMPARE(QModbusResponse::calculateDataSize(request), 4);
827
828 QModbusResponse::registerDataSizeCalculator(fc: QModbusResponse::WriteSingleCoil,
829 func: [](const QModbusResponse &)->int {
830 return 15;
831 });
832 QCOMPARE(QModbusResponse::calculateDataSize(response), 15);
833
834 QModbusResponse::registerDataSizeCalculator(fc: QModbusResponse::WriteSingleCoil, func: nullptr);
835 QCOMPARE(QModbusResponse::calculateDataSize(response), 4);
836
837 // custom
838 QModbusPdu::FunctionCode custom = QModbusPdu::FunctionCode(0x30);
839 request.setFunctionCode(custom);
840 QCOMPARE(QModbusRequest::calculateDataSize(request), -1);
841
842 QModbusRequest::registerDataSizeCalculator(fc: custom, func: [](const QModbusRequest &)->int {
843 return 27;
844 });
845 QCOMPARE(QModbusRequest::calculateDataSize(request), 27);
846 }
847
848 void testCalculateLongDataSize()
849 {
850 QByteArray longData = QByteArray(128, ' ');
851 longData[0] = longData.size();
852 const QModbusResponse response(QModbusResponse::ReadCoils, longData);
853 QCOMPARE(QModbusResponse::calculateDataSize(response), 1 + longData.size());
854
855 const QModbusRequest wfrRequest(QModbusPdu::WriteFileRecord, longData);
856 QCOMPARE(QModbusRequest::calculateDataSize(wfrRequest), 1 + longData.size());
857
858 longData = QByteArray(4 + 128, ' ');
859 longData[4] = char(128);
860 const QModbusRequest wmcRequest(QModbusPdu::WriteMultipleCoils, longData);
861 QCOMPARE(QModbusRequest::calculateDataSize(wmcRequest), 1 + longData.size());
862
863 const QModbusRequest wmrRequest(QModbusPdu::WriteMultipleRegisters, longData);
864 QCOMPARE(QModbusRequest::calculateDataSize(wmrRequest), 1 + longData.size());
865 }
866};
867
868QTEST_MAIN(tst_QModbusPdu)
869
870#include "tst_qmodbuspdu.moc"
871

source code of qtserialbus/tests/auto/qmodbuspdu/tst_qmodbuspdu.cpp