diff options
-rw-r--r-- | src/serialport/qserialport_win.cpp | 9 | ||||
-rw-r--r-- | tests/auto/qserialport/tst_qserialport.cpp | 103 |
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" |