summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2014-07-26 01:31:28 +0400
committerDenis Shienkov <denis.shienkov@gmail.com>2014-07-30 10:32:40 +0200
commit26504a5fe1c13af3b84b60eb2a5eb754c80d3c22 (patch)
tree6963b6caea19d0229a7996809430e643146e8933
parent76f293bfb0fd7bab391f96ac822eacc40e4c5176 (diff)
downloadqtserialport-26504a5fe1c13af3b84b60eb2a5eb754c80d3c22.tar.gz
Fix events handling in waitForBytesWritten() method on Windows
In case of communication event is triggered in the waitForBytesWritten() method then necessary to process it with the _q_completeAsyncCommunication() method, but not with the _q_completeAsyncRead() method. Otherwise it leads to false filling of the readBuffer with the data that were read earlier (or with garbage) which remained in readChunkBuffer. The synchronous loopback autotest reproduces a bug without of this patch. Tested on Windows 7/8 with the on-board and USB serial ports, using Qt5. Task-number: QTBUG-40344 Change-Id: I679109b60f4058c4c6f7e5f02c1f70ba6039d8d8 Reviewed-by: Sergey Belyashov <Sergey.Belyashov@gmail.com>
-rw-r--r--src/serialport/qserialport_win.cpp6
-rw-r--r--tests/auto/qserialport/tst_qserialport.cpp51
2 files changed, 52 insertions, 5 deletions
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 3432fc9..a6e1df7 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -449,8 +449,10 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs)
return false;
}
- if (triggeredEvent == communicationOverlapped.hEvent
- || triggeredEvent == readCompletionOverlapped.hEvent) {
+ if (triggeredEvent == communicationOverlapped.hEvent) {
+ if (!_q_completeAsyncCommunication())
+ return false;
+ } else if (triggeredEvent == readCompletionOverlapped.hEvent) {
if (!_q_completeAsyncRead())
return false;
} else if (triggeredEvent == writeCompletionOverlapped.hEvent) {
diff --git a/tests/auto/qserialport/tst_qserialport.cpp b/tests/auto/qserialport/tst_qserialport.cpp
index 192541c..4709d13 100644
--- a/tests/auto/qserialport/tst_qserialport.cpp
+++ b/tests/auto/qserialport/tst_qserialport.cpp
@@ -104,13 +104,15 @@ private slots:
void waitForReadyReadWithOneByte();
void waitForReadyReadWithAlphabet();
+ void twoStageSynchronousLoopback();
+
protected slots:
void handleBytesWrittenAndExitLoopSlot(qint64 bytesWritten);
void handleBytesWrittenAndExitLoopSlot2(qint64 bytesWritten);
private:
#ifdef Q_OS_WIN
- void clearReceiver();
+ void clearReceiver(const QString &customReceiverName = QString());
#endif
QString m_senderPortName;
@@ -142,9 +144,10 @@ tst_QSerialPort::tst_QSerialPort()
// not expected). It is recommended to use this method for cleaning of
// read FIFO of receiver for those tests in which reception of data is
// required.
-void tst_QSerialPort::clearReceiver()
+void tst_QSerialPort::clearReceiver(const QString &customReceiverName)
{
- QSerialPort receiver(m_receiverPortName);
+ QSerialPort receiver(customReceiverName.isEmpty()
+ ? m_receiverPortName : customReceiverName);
if (receiver.open(QIODevice::ReadOnly))
enterLoopMsecs(100);
}
@@ -438,5 +441,47 @@ void tst_QSerialPort::waitForReadyReadWithAlphabet()
QVERIFY(readyReadSpy.count() > 0);
}
+void tst_QSerialPort::twoStageSynchronousLoopback()
+{
+#ifdef Q_OS_WIN
+ clearReceiver();
+ clearReceiver(m_senderPortName);
+#endif
+
+ QSerialPort senderPort(m_senderPortName);
+ QVERIFY(senderPort.open(QSerialPort::ReadWrite));
+
+ QSerialPort receiverPort(m_receiverPortName);
+ QVERIFY(receiverPort.open(QSerialPort::ReadWrite));
+
+ const int waitMsecs = 50;
+
+ // first stage
+ senderPort.write(newlineArray);
+ senderPort.waitForBytesWritten(waitMsecs);
+ QTest::qSleep(waitMsecs);
+ receiverPort.waitForReadyRead(waitMsecs);
+ QCOMPARE(newlineArray.size(), receiverPort.bytesAvailable());
+ receiverPort.write(receiverPort.readAll());
+ receiverPort.waitForBytesWritten(waitMsecs);
+ QTest::qSleep(waitMsecs);
+ senderPort.waitForReadyRead(waitMsecs);
+ QCOMPARE(newlineArray.size(), senderPort.bytesAvailable());
+ QCOMPARE(newlineArray, senderPort.readAll());
+
+ // second stage
+ senderPort.write(newlineArray);
+ senderPort.waitForBytesWritten(waitMsecs);
+ QTest::qSleep(waitMsecs);
+ receiverPort.waitForReadyRead(waitMsecs);
+ QCOMPARE(newlineArray.size(), receiverPort.bytesAvailable());
+ receiverPort.write(receiverPort.readAll());
+ receiverPort.waitForBytesWritten(waitMsecs);
+ QTest::qSleep(waitMsecs);
+ senderPort.waitForReadyRead(waitMsecs);
+ QCOMPARE(newlineArray.size(), senderPort.bytesAvailable());
+ QCOMPARE(newlineArray, senderPort.readAll());
+}
+
QTEST_MAIN(tst_QSerialPort)
#include "tst_qserialport.moc"