diff options
-rw-r--r-- | src/serialport/qserialport.h | 1 | ||||
-rw-r--r-- | src/serialport/qserialport_win.cpp | 19 | ||||
-rw-r--r-- | src/serialport/qserialport_win_p.h | 2 | ||||
-rw-r--r-- | tests/auto/qserialport/tst_qserialport.cpp | 155 |
4 files changed, 167 insertions, 10 deletions
diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h index d0f65b5..8a0bbb1 100644 --- a/src/serialport/qserialport.h +++ b/src/serialport/qserialport.h @@ -287,6 +287,7 @@ private: Q_PRIVATE_SLOT(d_func(), bool _q_completeAsyncCommunication()) Q_PRIVATE_SLOT(d_func(), bool _q_completeAsyncRead()) Q_PRIVATE_SLOT(d_func(), bool _q_completeAsyncWrite()) + Q_PRIVATE_SLOT(d_func(), bool _q_startAsyncWrite()) #endif }; diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index ecbf464..18cef1e 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -259,7 +259,7 @@ bool QSerialPortPrivate::setRequestToSend(bool set) bool QSerialPortPrivate::flush() { - return startAsyncWrite(); + return _q_startAsyncWrite(); } bool QSerialPortPrivate::clear(QSerialPort::Directions directions) @@ -313,7 +313,7 @@ void QSerialPortPrivate::startWriting() if (!writeStarted) { if (!startAsyncWriteTimer) { startAsyncWriteTimer = new QTimer(q); - q->connect(startAsyncWriteTimer, SIGNAL(timeout()), q, SLOT(_q_completeAsyncWrite())); + q->connect(startAsyncWriteTimer, SIGNAL(timeout()), q, SLOT(_q_startAsyncWrite())); startAsyncWriteTimer->setSingleShot(true); } startAsyncWriteTimer->start(0); @@ -327,7 +327,7 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs) QElapsedTimer stopWatch; stopWatch.start(); - if (!writeStarted && !startAsyncWrite()) + if (!writeStarted && !_q_startAsyncWrite()) return false; const qint64 initialReadBufferSize = readBuffer.size(); @@ -381,7 +381,7 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs) QElapsedTimer stopWatch; stopWatch.start(); - if (!writeStarted && !startAsyncWrite()) + if (!writeStarted && !_q_startAsyncWrite()) return false; forever { @@ -543,17 +543,18 @@ bool QSerialPortPrivate::_q_completeAsyncWrite() Q_Q(QSerialPort); if (writeStarted) { - writeStarted = false; const qint64 bytesTransferred = handleOverlappedResult(QSerialPort::Output, writeCompletionOverlapped); - if (bytesTransferred == qint64(-1)) + if (bytesTransferred == qint64(-1)) { + writeStarted = false; return false; - if (bytesTransferred > 0) { + } else if (bytesTransferred > 0) { writeBuffer.free(bytesTransferred); emit q->bytesWritten(bytesTransferred); } + writeStarted = false; } - return startAsyncWrite(); + return _q_startAsyncWrite(); } bool QSerialPortPrivate::startAsyncCommunication() @@ -605,7 +606,7 @@ bool QSerialPortPrivate::startAsyncRead() return true; } -bool QSerialPortPrivate::startAsyncWrite() +bool QSerialPortPrivate::_q_startAsyncWrite() { Q_Q(QSerialPort); diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h index f4297ef..cf30c18 100644 --- a/src/serialport/qserialport_win_p.h +++ b/src/serialport/qserialport_win_p.h @@ -108,7 +108,7 @@ public: bool startAsyncCommunication(); bool startAsyncRead(); - bool startAsyncWrite(); + bool _q_startAsyncWrite(); bool emulateErrorPolicy(); void emitReadyRead(); diff --git a/tests/auto/qserialport/tst_qserialport.cpp b/tests/auto/qserialport/tst_qserialport.cpp index 9e8f659..6fcb941 100644 --- a/tests/auto/qserialport/tst_qserialport.cpp +++ b/tests/auto/qserialport/tst_qserialport.cpp @@ -46,6 +46,7 @@ Q_DECLARE_METATYPE(QSerialPort::SerialPortError); Q_DECLARE_METATYPE(QIODevice::OpenMode); Q_DECLARE_METATYPE(QIODevice::OpenModeFlag); +Q_DECLARE_METATYPE(Qt::ConnectionType); class tst_QSerialPort : public QObject { @@ -108,6 +109,12 @@ private slots: void synchronousReadWrite(); + void asynchronousWriteByBytesWritten_data(); + void asynchronousWriteByBytesWritten(); + + void asynchronousWriteByTimer_data(); + void asynchronousWriteByTimer(); + protected slots: void handleBytesWrittenAndExitLoopSlot(qint64 bytesWritten); void handleBytesWrittenAndExitLoopSlot2(qint64 bytesWritten); @@ -511,5 +518,153 @@ void tst_QSerialPort::synchronousReadWrite() QCOMPARE(writeData, readData); } +class AsyncReader : public QObject +{ + Q_OBJECT +public: + explicit AsyncReader(QSerialPort &port, Qt::ConnectionType connectionType, int expectedBytesCount) + : serialPort(port), expectedBytesCount(expectedBytesCount) + { + connect(&serialPort, SIGNAL(readyRead()), this, SLOT(receive()), connectionType); + } + +private slots: + void receive() + { + if (serialPort.bytesAvailable() < expectedBytesCount) + return; + tst_QSerialPort::exitLoop(); + } + +private: + QSerialPort &serialPort; + const int expectedBytesCount; +}; + +class AsyncWriterByBytesWritten : public QObject +{ + Q_OBJECT +public: + explicit AsyncWriterByBytesWritten( + QSerialPort &port, Qt::ConnectionType connectionType, const QByteArray &dataToWrite) + : serialPort(port), writeChunkSize(0) + { + writeBuffer.setData(dataToWrite); + writeBuffer.open(QIODevice::ReadOnly); + connect(&serialPort, SIGNAL(bytesWritten(qint64)), this, SLOT(send()), connectionType); + send(); + } + +private slots: + void send() + { + if (writeBuffer.bytesAvailable() > 0) + serialPort.write(writeBuffer.read(++writeChunkSize)); + } + +private: + QSerialPort &serialPort; + QBuffer writeBuffer; + int writeChunkSize; +}; + +void tst_QSerialPort::asynchronousWriteByBytesWritten_data() +{ + QTest::addColumn<Qt::ConnectionType>("readConnectionType"); + QTest::addColumn<Qt::ConnectionType>("writeConnectionType"); + + QTest::newRow("BothQueued") << Qt::QueuedConnection << Qt::QueuedConnection; + QTest::newRow("BothDirect") << Qt::DirectConnection << Qt::DirectConnection; + QTest::newRow("ReadDirectWriteQueued") << Qt::DirectConnection << Qt::QueuedConnection; + QTest::newRow("ReadQueuedWriteDirect") << Qt::QueuedConnection << Qt::DirectConnection; +} + +void tst_QSerialPort::asynchronousWriteByBytesWritten() +{ +#ifdef Q_OS_WIN + clearReceiver(); +#endif + + QFETCH(Qt::ConnectionType, readConnectionType); + QFETCH(Qt::ConnectionType, writeConnectionType); + + QSerialPort receiverPort(m_receiverPortName); + QVERIFY(receiverPort.open(QSerialPort::ReadOnly)); + AsyncReader reader(receiverPort, readConnectionType, alphabetArray.size()); + + QSerialPort senderPort(m_senderPortName); + QVERIFY(senderPort.open(QSerialPort::WriteOnly)); + AsyncWriterByBytesWritten writer(senderPort, writeConnectionType, alphabetArray); + + enterLoop(1); + QVERIFY2(!timeout(), "Timed out when waiting for the read or write."); + QCOMPARE(receiverPort.bytesAvailable(), qint64(alphabetArray.size())); + QCOMPARE(receiverPort.readAll(), alphabetArray); +} + +class AsyncWriterByTimer : public QObject +{ + Q_OBJECT +public: + explicit AsyncWriterByTimer( + QSerialPort &port, Qt::ConnectionType connectionType, const QByteArray &dataToWrite) + : serialPort(port), writeChunkSize(0) + { + writeBuffer.setData(dataToWrite); + writeBuffer.open(QIODevice::ReadOnly); + connect(&timer, SIGNAL(timeout()), this, SLOT(send()), connectionType); + timer.start(0); + } + +private slots: + void send() + { + if (writeBuffer.bytesAvailable() > 0) + serialPort.write(writeBuffer.read(++writeChunkSize)); + else + timer.stop(); + } + +private: + QSerialPort &serialPort; + QBuffer writeBuffer; + int writeChunkSize; + QTimer timer; +}; + +void tst_QSerialPort::asynchronousWriteByTimer_data() +{ + QTest::addColumn<Qt::ConnectionType>("readConnectionType"); + QTest::addColumn<Qt::ConnectionType>("writeConnectionType"); + + QTest::newRow("BothQueued") << Qt::QueuedConnection << Qt::QueuedConnection; + QTest::newRow("BothDirect") << Qt::DirectConnection << Qt::DirectConnection; + QTest::newRow("ReadDirectWriteQueued") << Qt::DirectConnection << Qt::QueuedConnection; + QTest::newRow("ReadQueuedWriteDirect") << Qt::QueuedConnection << Qt::DirectConnection; +} + +void tst_QSerialPort::asynchronousWriteByTimer() +{ +#ifdef Q_OS_WIN + clearReceiver(); +#endif + + QFETCH(Qt::ConnectionType, readConnectionType); + QFETCH(Qt::ConnectionType, writeConnectionType); + + QSerialPort receiverPort(m_receiverPortName); + QVERIFY(receiverPort.open(QSerialPort::ReadOnly)); + AsyncReader reader(receiverPort, readConnectionType, alphabetArray.size()); + + QSerialPort senderPort(m_senderPortName); + QVERIFY(senderPort.open(QSerialPort::WriteOnly)); + AsyncWriterByTimer writer(senderPort, writeConnectionType, alphabetArray); + + enterLoop(1); + QVERIFY2(!timeout(), "Timed out when waiting for the read or write."); + QCOMPARE(receiverPort.bytesAvailable(), qint64(alphabetArray.size())); + QCOMPARE(receiverPort.readAll(), alphabetArray); +} + QTEST_MAIN(tst_QSerialPort) #include "tst_qserialport.moc" |