diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2014-05-27 19:34:06 +0400 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-06-03 14:08:41 +0200 |
commit | d598a00e823d8509fc67fc2452dcaf2939092804 (patch) | |
tree | 7c51ffa04a408da27e453c6527838c641d9790a1 /tests | |
parent | 2271479ff5d58b792af2c3823afe0f88fbf047ea (diff) | |
download | qtserialport-d598a00e823d8509fc67fc2452dcaf2939092804.tar.gz |
Fix waitForReadyRead() on windows
The commit 2360c401ae2012ed1b5a2b470a088cbbdb0d7f27 introduced an
regression into waitForReadyRead(). Before this commit each read
transaction was started again until the zero number of bytes will
returns from FIFO. When FIFO is empty, all data has been read, and
only then the waitForReadyRead() return true. I.e. condition
"qint64(readBuffer.size()) != currentReadBufferSize" does not mean
that reading is finished.
But after that commit this condition is incorrect, because now each
read operation started once and can not return zero bytes (in case
the number of read bytes less than ReadChunkSize). Thus it led to
returning of TimeoutError error.
Now, this issue has been fixed. Also is added the set of auto-tests
to testing of the waitForReadyRead() method.
Tested on Windows 7/8 using Qt5 and then Qt4.
Task-number: QTBUG-39314
Change-Id: I8abbf986c2a1cc77af634ddbc1747fb46f416a39
Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/qserialport/tst_qserialport.cpp | 103 |
1 files changed, 103 insertions, 0 deletions
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" |