summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/serialport/qserialport_win.cpp9
-rw-r--r--tests/auto/qserialport/tst_qserialport.cpp103
2 files changed, 110 insertions, 2 deletions
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 5411d17..111a8ce 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -403,10 +403,15 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
_q_completeAsyncCommunication();
} else if (triggeredEvent == readCompletionOverlapped.hEvent) {
_q_completeAsyncRead();
- if (qint64(readBuffer.size()) != currentReadBufferSize)
+ const qint64 readBytesForOneReadOperation = qint64(readBuffer.size()) - currentReadBufferSize;
+ if (readBytesForOneReadOperation == ReadChunkSize) {
currentReadBufferSize = readBuffer.size();
- else if (initialReadBufferSize != currentReadBufferSize)
+ } else if (readBytesForOneReadOperation == 0) {
+ if (initialReadBufferSize != currentReadBufferSize)
+ return true;
+ } else {
return true;
+ }
} else if (triggeredEvent == writeCompletionOverlapped.hEvent) {
_q_completeAsyncWrite();
} else {
diff --git a/tests/auto/qserialport/tst_qserialport.cpp b/tests/auto/qserialport/tst_qserialport.cpp
index 96d3788..192541c 100644
--- a/tests/auto/qserialport/tst_qserialport.cpp
+++ b/tests/auto/qserialport/tst_qserialport.cpp
@@ -60,6 +60,18 @@ public:
--loopLevel;
}
+ static void enterLoopMsecs(int msecs)
+ {
+ ++loopLevel;
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
+ QTestEventLoop::instance().enterLoopMSecs(msecs);
+#else
+ Q_UNUSED(msecs);
+ QTestEventLoop::instance().enterLoop(1);
+#endif
+ --loopLevel;
+ }
+
static void exitLoop()
{
if (loopLevel > 0)
@@ -88,11 +100,19 @@ private slots:
void waitForBytesWritten();
+ void waitForReadyReadWithTimeout();
+ void waitForReadyReadWithOneByte();
+ void waitForReadyReadWithAlphabet();
+
protected slots:
void handleBytesWrittenAndExitLoopSlot(qint64 bytesWritten);
void handleBytesWrittenAndExitLoopSlot2(qint64 bytesWritten);
private:
+#ifdef Q_OS_WIN
+ void clearReceiver();
+#endif
+
QString m_senderPortName;
QString m_receiverPortName;
QStringList m_availablePortNames;
@@ -111,6 +131,25 @@ tst_QSerialPort::tst_QSerialPort()
{
}
+#ifdef Q_OS_WIN
+// This method is a workaround for the "com0com" virtual serial port
+// driver, which is installed on CI. The problem is that the close/clear
+// methods have no effect on sender serial port. If any data didn't manage
+// to be transferred before closing, then this data will continue to be
+// transferred at next opening of sender port.
+// Thus, this behavior influences other tests and leads to the wrong results
+// (e.g. the receiver port on other test can receive some data which are
+// 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()
+{
+ QSerialPort receiver(m_receiverPortName);
+ if (receiver.open(QIODevice::ReadOnly))
+ enterLoopMsecs(100);
+}
+#endif
+
void tst_QSerialPort::initTestCase()
{
m_senderPortName = QString::fromLocal8Bit(qgetenv("QTEST_SERIALPORT_SENDER"));
@@ -335,5 +374,69 @@ void tst_QSerialPort::waitForBytesWritten()
QVERIFY(toWrite > serialPort.bytesToWrite());
}
+void tst_QSerialPort::waitForReadyReadWithTimeout()
+{
+#ifdef Q_OS_WIN
+ clearReceiver();
+ // the dummy device on other side also has to be open
+ QSerialPort dummySerialPort(m_senderPortName);
+ QVERIFY(dummySerialPort.open(QIODevice::WriteOnly));
+#endif
+
+ QSerialPort receiverSerialPort(m_receiverPortName);
+ QVERIFY(receiverSerialPort.open(QIODevice::ReadOnly));
+ QVERIFY(!receiverSerialPort.waitForReadyRead(5));
+ QCOMPARE(receiverSerialPort.bytesAvailable(), qint64(0));
+ QCOMPARE(receiverSerialPort.error(), QSerialPort::TimeoutError);
+}
+
+void tst_QSerialPort::waitForReadyReadWithOneByte()
+{
+#ifdef Q_OS_WIN
+ clearReceiver();
+#endif
+
+ const qint64 oneByte = 1;
+ const int waitMsecs = 50;
+
+ QSerialPort senderSerialPort(m_senderPortName);
+ QVERIFY(senderSerialPort.open(QIODevice::WriteOnly));
+ QSerialPort receiverSerialPort(m_receiverPortName);
+ QSignalSpy readyReadSpy(&receiverSerialPort, SIGNAL(readyRead()));
+ QVERIFY(readyReadSpy.isValid());
+ QVERIFY(receiverSerialPort.open(QIODevice::ReadOnly));
+ QCOMPARE(senderSerialPort.write(alphabetArray.constData(), oneByte), oneByte);
+ QVERIFY(senderSerialPort.waitForBytesWritten(waitMsecs));
+ QVERIFY(receiverSerialPort.waitForReadyRead(waitMsecs));
+ QCOMPARE(receiverSerialPort.bytesAvailable(), oneByte);
+ QCOMPARE(receiverSerialPort.error(), QSerialPort::NoError);
+ QCOMPARE(readyReadSpy.count(), 1);
+}
+
+void tst_QSerialPort::waitForReadyReadWithAlphabet()
+{
+#ifdef Q_OS_WIN
+ clearReceiver();
+#endif
+
+ const int waitMsecs = 50;
+
+ QSerialPort senderSerialPort(m_senderPortName);
+ QVERIFY(senderSerialPort.open(QIODevice::WriteOnly));
+ QSerialPort receiverSerialPort(m_receiverPortName);
+ QSignalSpy readyReadSpy(&receiverSerialPort, SIGNAL(readyRead()));
+ QVERIFY(readyReadSpy.isValid());
+ QVERIFY(receiverSerialPort.open(QIODevice::ReadOnly));
+ QCOMPARE(senderSerialPort.write(alphabetArray), qint64(alphabetArray.size()));
+ QVERIFY(senderSerialPort.waitForBytesWritten(waitMsecs));
+
+ do {
+ QVERIFY(receiverSerialPort.waitForReadyRead(waitMsecs));
+ } while (receiverSerialPort.bytesAvailable() < qint64(alphabetArray.size()));
+
+ QCOMPARE(receiverSerialPort.error(), QSerialPort::NoError);
+ QVERIFY(readyReadSpy.count() > 0);
+}
+
QTEST_MAIN(tst_QSerialPort)
#include "tst_qserialport.moc"