diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2015-06-28 00:11:29 +0300 |
---|---|---|
committer | Denis Shienkov <denis.shienkov@gmail.com> | 2015-07-07 14:00:58 +0000 |
commit | b32740001f735be9f0938f85d325dc2cf3dbe598 (patch) | |
tree | ce8114932e30c620642e68ca5fdfe6694fb2b356 /tests/auto | |
parent | 77c48a0e22c1048226832e6b845d72da9d5b317f (diff) | |
download | qtserialport-b32740001f735be9f0938f85d325dc2cf3dbe598.tar.gz |
Fix reading when switching from asynchronous to synchronous approach
If one wants to use the asynchronous approach (using the signals and
slots), and then - the synchronous (using the waitForXX functions) then
synchronous reading stalls because the waitForReadyRead() method
always returns the TimeoutError code.
The reason is that the signal readyRead() is emitted before the
startAsyncRead() (or the startAsyncCommunication()) called inside of
completeAsyncRead().
Need to emit the readyRead() only after the next asynchronous reading
(the startAsyncRead() or the startAsyncCommunication()) was cocked.
Now the behavior is similar to behavior of QWindowsPipeReader. Besides,
the auto-test which reveals this issue is added.
Tested with the virtual com0com serial ports, using the auto-tests and
set of the examples.
Change-Id: I64bfb871d17c179f474d6672546e532566913a7f
Reviewed-by: Sergey Belyashov <Sergey.Belyashov@gmail.com>
Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
Reviewed-by: Andrzej Ostruszka <andrzej.ostruszka@gmail.com>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/qserialport/tst_qserialport.cpp | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/tests/auto/qserialport/tst_qserialport.cpp b/tests/auto/qserialport/tst_qserialport.cpp index 1a714b2..54118af 100644 --- a/tests/auto/qserialport/tst_qserialport.cpp +++ b/tests/auto/qserialport/tst_qserialport.cpp @@ -35,6 +35,8 @@ #include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo> +#include <QThread> + Q_DECLARE_METATYPE(QSerialPort::SerialPortError); Q_DECLARE_METATYPE(QIODevice::OpenMode); Q_DECLARE_METATYPE(QIODevice::OpenModeFlag); @@ -105,6 +107,7 @@ private slots: #ifdef Q_OS_WIN void readBufferOverflow(); void readAfterInputClear(); + void synchronousReadWriteAfterAsynchronousReadWrite(); #endif void controlBreak(); @@ -739,6 +742,107 @@ void tst_QSerialPort::readAfterInputClear() // No more bytes available QVERIFY(receiverPort.bytesAvailable() == 0); } + +class MasterTransactor : public QObject +{ + Q_OBJECT +public: + explicit MasterTransactor(const QString &name) + : serialPort(name) + { + } + +public slots: + void open() + { + if (serialPort.open(QSerialPort::ReadWrite)) { + createAsynchronousConnection(); + serialPort.write("A", 1); + } + } + +private slots: + void synchronousTransaction() + { + serialPort.write("B", 1); + if (serialPort.waitForBytesWritten(100)) { + if (serialPort.waitForReadyRead(100)) + tst_QSerialPort::exitLoop(); + } + } + + void transaction() + { + deleteAsyncronousConnection(); + synchronousTransaction(); + } + +private: + void createAsynchronousConnection() + { + connect(&serialPort, &QSerialPort::readyRead, this, &MasterTransactor::transaction); + } + + void deleteAsyncronousConnection() + { + serialPort.disconnect(); + } + + QSerialPort serialPort; +}; + +class SlaveTransactor : public QObject +{ + Q_OBJECT +public: + explicit SlaveTransactor(const QString &name) + : serialPort(new QSerialPort(name, this)) + { + connect(serialPort, &QSerialPort::readyRead, this, &SlaveTransactor::transaction); + } + +public slots: + void open() + { + if (serialPort->open(QSerialPort::ReadWrite)) + emit ready(); + } + +signals: + void ready(); + +private slots: + void transaction() + { + serialPort->write("Z", 1); + } + +private: + QSerialPort *serialPort; +}; + +void tst_QSerialPort::synchronousReadWriteAfterAsynchronousReadWrite() +{ + MasterTransactor master(m_senderPortName); + SlaveTransactor *slave = new SlaveTransactor(m_receiverPortName); + + QThread thread; + slave->moveToThread(&thread); + thread.start(); + + QObject::connect(&thread, &QThread::finished, slave, &SlaveTransactor::deleteLater); + QObject::connect(slave, &SlaveTransactor::ready, &master, &MasterTransactor::open); + + QMetaObject::invokeMethod(slave, "open", Qt::QueuedConnection); + + tst_QSerialPort::enterLoopMsecs(500); + + thread.quit(); + thread.wait(); + + QVERIFY2(!timeout(), "Timed out when testing of transactions."); +} + #endif class BreakReader : public QObject |