From 55b29ef40df2b1f91ecab06c492ca70ba5e0297f Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 10 Jul 2014 11:40:18 +0400 Subject: Return from the loop if a port name is found The function devicePortName() search in the Registry the names of ports by names of registry keys. At first looks for value of a key of "PortName", and then of "PortNumber" key. Thus, the first found value shall stop search and do not try to continue. Tested on Windows 7/8 using Qt4 and then Qt5. Change-Id: I98b00ff043a3b08476fec0a57b0d36ce65fc8d63 Reviewed-by: Sergey Belyashov --- src/serialport/qserialportinfo_win.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp index dbef3141..0e01ac72 100644 --- a/src/serialport/qserialportinfo_win.cpp +++ b/src/serialport/qserialportinfo_win.cpp @@ -182,6 +182,9 @@ static QString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInf } break; } + + if (!portName.isEmpty()) + break; } ::RegCloseKey(key); return portName; -- cgit v1.2.3 From 7328fe502a08ff26d70ee5d137e554a77a118f9b Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Thu, 10 Jul 2014 15:15:23 +0200 Subject: Doc: Edited example documentation. -added information about how to run the example by including a file from qtbase/doc/global -edited summary sections -added \brief. -removed image captions. Our Qt 5 CSS files don't handle them. Task-number: QTBUG-33597 Change-Id: If3293aa9d98b662f20af2af7030b0ab0fb1e8401 Reviewed-by: Denis Shienkov Reviewed-by: Leena Miettinen --- examples/serialport/doc/blockingmaster.qdoc | 12 +++++++----- examples/serialport/doc/blockingslave.qdoc | 10 +++++++--- examples/serialport/doc/cenumerator.qdoc | 14 ++++++++------ examples/serialport/doc/creaderasync.qdoc | 8 ++++++-- examples/serialport/doc/creadersync.qdoc | 12 ++++++++---- examples/serialport/doc/cwriterasync.qdoc | 13 ++++++++----- examples/serialport/doc/cwritersync.qdoc | 12 ++++++++---- examples/serialport/doc/enumerator.qdoc | 8 ++++++-- examples/serialport/doc/terminal.qdoc | 10 +++++++--- examples/serialport/examples.qdoc | 25 +++++++++++-------------- 10 files changed, 76 insertions(+), 48 deletions(-) diff --git a/examples/serialport/doc/blockingmaster.qdoc b/examples/serialport/doc/blockingmaster.qdoc index 32176a13..0aa0c3f2 100644 --- a/examples/serialport/doc/blockingmaster.qdoc +++ b/examples/serialport/doc/blockingmaster.qdoc @@ -2,6 +2,7 @@ ** ** Copyright (C) 2011 - 2012 Denis Shienkov ** Copyright (C) 2012 - 2013 Laszlo Papp +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -30,13 +31,12 @@ \example blockingmaster \title Blocking Master Example \ingroup qtserialport-examples - \brief Explains how to use the synchronous API of QSerialPort. + \brief Shows how to use the synchronous API of QSerialPort in a worker thread. - The blocking master example shows how to create an application for a - serial interface using the synchronous API of QSerialPort in a worker - thread. + \e{Blocking Master} shows how to create an application for a serial + interface using the synchronous API of QSerialPort in a worker thread. - \image blockingmaster-example.png Screenshot of the blocking master example + \image blockingmaster-example.png QSerialPort supports two programming alternatives: @@ -162,4 +162,6 @@ \snippet blockingmaster/masterthread.cpp 13 \sa {Terminal Example}, {Blocking Slave Example} + + \include examples-run.qdocinc */ diff --git a/examples/serialport/doc/blockingslave.qdoc b/examples/serialport/doc/blockingslave.qdoc index df35bfc0..a2e3a6b1 100644 --- a/examples/serialport/doc/blockingslave.qdoc +++ b/examples/serialport/doc/blockingslave.qdoc @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2011 - 2012 Denis Shienkov +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -29,11 +30,12 @@ \example blockingslave \title Blocking Slave Example \ingroup qtserialport-examples + \brief Shows how to use the synchronous API of QSerialPort in a non-GUI thread. - The Blocking Slave example shows how to create a application for a - serial interface using QSerialPort's synchronous API in a non-GUI thread. + \e{Blocking Slave} shows how to create an application for a serial interface + using QSerialPort's synchronous API in a non-GUI thread. - \image blockingslave-example.png Screenshot of the Blocking Slave example + \image blockingslave-example.png QSerialPort supports two general programming approaches: @@ -160,4 +162,6 @@ \snippet blockingslave/slavethread.cpp 13 \sa {Terminal Example}, {Blocking Master Example} + + \include examples-run.qdocinc */ diff --git a/examples/serialport/doc/cenumerator.qdoc b/examples/serialport/doc/cenumerator.qdoc index 0766931a..83718982 100644 --- a/examples/serialport/doc/cenumerator.qdoc +++ b/examples/serialport/doc/cenumerator.qdoc @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Laszlo Papp +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -28,18 +29,19 @@ /*! \example cenumerator \title Command Line Enumerator Example - \ingroup qtserialport-examples + \ingroup qtserialport-example + \brief Shows how to get information about serial devices in a system. - The Command Line Enumerator example shows how to use the class - QSerialPortInfo for getting information about serial devices that are present - in the system. + \e{Command Line Enumerator} shows how to use the class QSerialPortInfo for + getting information about serial devices that are present in the system. - \image cenumerator-example.png Screenshot of the Command Line Enumerator - example + \image cenumerator-example.png This command line example displays information about serial ports in a console, provided by the class QSerialPortInfo. For getting information about the available ports, use the static method \l{QSerialPortInfo::availablePorts()}{availablePorts()}. + + \include examples-run.qdocinc */ diff --git a/examples/serialport/doc/creaderasync.qdoc b/examples/serialport/doc/creaderasync.qdoc index a8b21013..ff5e9c61 100644 --- a/examples/serialport/doc/creaderasync.qdoc +++ b/examples/serialport/doc/creaderasync.qdoc @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Laszlo Papp +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -29,12 +30,13 @@ \example creaderasync \title Command Line Reader Async Example \ingroup qtserialport-examples + \brief Shows how to receive data asynchronously over serial port. - The Command Line Reader Async example shows how to use the QSerialPort class for + \e{Command Line Reader Async} shows how to use the QSerialPort class for receiving data asynchronously over the selected serial port with the desired settings. - \image creaderasync-example.png Screenshot of the Command Line Reader Async example + \image creaderasync-example.png This command line reader async example receives data asynchronously over the selected serial port in a console, provided by the QSerialPort class. @@ -42,4 +44,6 @@ For receiving data synchronously over the selected serial port, use the \l{QSerialPort::read()}{read()} or \l{QSerialPort::readAll()}{readAll()} methods, and \l{QIODevice::readyRead()}{readyRead()} signal. + + \include examples-run.qdocinc */ diff --git a/examples/serialport/doc/creadersync.qdoc b/examples/serialport/doc/creadersync.qdoc index 3b6c968f..6c3f4a89 100644 --- a/examples/serialport/doc/creadersync.qdoc +++ b/examples/serialport/doc/creadersync.qdoc @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Laszlo Papp +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -29,12 +30,13 @@ \example creadersync \title Command Line Reader Sync Example \ingroup qtserialport-examples + \brief Shows how to receive data synchronously over serial port. - The Command Line Reader Sync example shows how to use the QSerialPort class for - receiving data synchronously over the selected serial port with the desired - settings. + \e{Command Line Reader Sync} shows how to use the QSerialPort class + for receiving data synchronously over the selected serial port with the + desired settings. - \image creadersync-example.png Screenshot of the Command Line Reader Sync example + \image creadersync-example.png This command line reader sync example receives data synchronously over the selected serial port in a console, provided by the QSerialPort class. @@ -42,4 +44,6 @@ For receiving data synchronously over the selected serial port, use the \l{QSerialPort::read()}{read()} or \l{QSerialPort::readAll()}{readAll()}, and \l{QIODevice::waitForReadyRead()}{waitForReadyRead()} methods. + + \include examples-run.qdocinc */ diff --git a/examples/serialport/doc/cwriterasync.qdoc b/examples/serialport/doc/cwriterasync.qdoc index 884435bc..b10f2aaf 100644 --- a/examples/serialport/doc/cwriterasync.qdoc +++ b/examples/serialport/doc/cwriterasync.qdoc @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Laszlo Papp +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -29,13 +30,13 @@ \example cwriterasync \title Command Line Writer Async Example \ingroup qtserialport-examples + \brief Shows how to send data asynchronously over serial port. - The Command Line Writer Async example shows how to use the QSerialPort class - for sending data asynchronously over the selected serial port with the - desired settings. + \e{Command Line Writer Async} shows how to use the QSerialPort class for + sending data asynchronously over the selected serial port with the desired + settings. - \image cwriterasync-example.png Screenshot of the Command Line Writer Async - example + \image cwriterasync-example.png This command line writer async example sends data asynchronously over the selected serial port in a console, provided by the QSerialPort class. @@ -43,4 +44,6 @@ For sending data asynchronously over the selected serial port, use the \l{QIODevice::write()}{write()} method and \l{QIODevice::bytesWritten()}{bytesWritten()} signal. + + \include examples-run.qdocinc */ diff --git a/examples/serialport/doc/cwritersync.qdoc b/examples/serialport/doc/cwritersync.qdoc index 05858ef7..03086e05 100644 --- a/examples/serialport/doc/cwritersync.qdoc +++ b/examples/serialport/doc/cwritersync.qdoc @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Laszlo Papp +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -29,12 +30,13 @@ \example cwritersync \title Command Line Writer Sync Example \ingroup qtserialport-examples + \brief Shows how to send data synchronously over serial port. - The Command Line Writer Sync example shows how to use the QSerialPort class - for sending data synchronously over the selected serial port with the - desired settings. + \e{Command Line Writer Sync} shows how to use the QSerialPort class for + sending data synchronously over the selected serial port with the desired + settings. - \image cwritersync-example.png Screenshot of the Command Line Writer Sync example + \image cwritersync-example.png This command line writer sync example sends data synchronously over the selected serial port in a console, provided by the QSerialPort class. @@ -42,4 +44,6 @@ For sending data synchronously over the selected serial port, use the \l{QIODevice::write()}{write()} and \l{QIODevice::waitForBytesWritten()}{waitForBytesWritten()} methods. + + \include examples-run.qdocinc */ diff --git a/examples/serialport/doc/enumerator.qdoc b/examples/serialport/doc/enumerator.qdoc index 0847d8a8..326fdb4b 100644 --- a/examples/serialport/doc/enumerator.qdoc +++ b/examples/serialport/doc/enumerator.qdoc @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2011 - 2012 Denis Shienkov +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -29,15 +30,18 @@ \example enumerator \title Enumerator Example \ingroup qtserialport-examples + \brief Shows how to display information about serial devices in a system. - The Enumerator example shows how to use the class QSerialPortInfo for + \e Enumerator shows how to use the class QSerialPortInfo for getting information about serial devices that are present in the system. - \image enumerator-example.png Screenshot of the Enumerator example + \image enumerator-example.png This GUI example displays information about serial ports in a widget, provided by the class QSerialPortInfo. For getting information about the available ports, use the static method \l{QSerialPortInfo::availablePorts()}{availablePorts()}. + + \include examples-run.qdocinc */ diff --git a/examples/serialport/doc/terminal.qdoc b/examples/serialport/doc/terminal.qdoc index ed8fa023..423d6108 100644 --- a/examples/serialport/doc/terminal.qdoc +++ b/examples/serialport/doc/terminal.qdoc @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2011 - 2012 Denis Shienkov +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -29,11 +30,12 @@ \example terminal \title Terminal Example \ingroup qtserialport-examples + \brief Shows how to use various features of QSerialPort. - The Terminal example shows how to create a terminal for a simple serial - interface by using Qt Serial Port. + \e Terminal shows how to create a terminal for a simple serial interface by + using \l{Qt Serial Port}. - \image terminal-example.png Screenshot of the Terminal example + \image terminal-example.png This example shows the main features of the QSerialPort class, like configuration, I/O implementation and so forth. Also, the class @@ -143,4 +145,6 @@ port. \sa {Blocking Slave Example} + + \include examples-run.qdocinc */ diff --git a/examples/serialport/examples.qdoc b/examples/serialport/examples.qdoc index 6e5f3c4a..51858b97 100644 --- a/examples/serialport/examples.qdoc +++ b/examples/serialport/examples.qdoc @@ -2,6 +2,7 @@ ** ** Copyright (C) 2011-2012 Denis Shienkov ** Copyright (C) 2012 Laszlo Papp +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -28,21 +29,17 @@ /*! \title Qt Serial Port Examples - \page examples.html + \group qtserialport-examples \brief List of serial port examples - The module provides the following examples for reference to - help understand the API usage: + The \l{Qt Serial Port} module provides the following examples for reference + to help understand the API usage. + + \section1 Running the Examples + + To run the examples from \l{Qt Creator Manual}{Qt Creator}, open the \gui + Welcome mode and select the example from \gui Examples. + For more information, visit + \l{Qt Creator: Building and Running an Example}{Building and Running an Example}. - \list - \li \l blockingmaster - \li \l blockingslave - \li \l cenumerator - \li \l cwriterasync - \li \l cwritersync - \li \l creaderasync - \li \l creadersync - \li \l enumerator - \li \l terminal - \endlist */ -- cgit v1.2.3 From 76f293bfb0fd7bab391f96ac822eacc40e4c5176 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Fri, 11 Jul 2014 16:32:28 +0400 Subject: Add the synchronous loopback data verification test Good reason to check of data correctness at transferring and receiving. In this test are used two serial ports, connected in a null-modem mode: http://en.wikipedia.org/wiki/Null_modem . The sender port transfers data to the receiver port. After data are received is carried out check of equivalence of the transferred and received data. Before run of testing it is necessary to set two variable environments QTEST_SERIALPORT_SENDER and QTEST_SERIALPORT_RECEIVER to specify names of used serial ports. This test can reveal errors related with the internal data processing and also errors of synchronous I/O inside of QSerialPort. This test is placed in separate "benchmarks" category not to mix-up with "manual" and "auto" categories, because this test is closer to "benchmarks" by own functionality. Tested on Windows 7/8 with the virtual com0com serial ports, using Qt4 and then Qt5. Change-Id: Ie6f87b50784bce211cf68c16cf75f79d12a8564f Reviewed-by: Denis Shienkov Reviewed-by: Konstantin Ritt --- tests/benchmarks/benchmarks.pro | 2 + tests/benchmarks/qserialport/qserialport.pro | 11 ++ tests/benchmarks/qserialport/tst_qserialport.cpp | 144 +++++++++++++++++++++++ tests/tests.pro | 2 +- 4 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 tests/benchmarks/benchmarks.pro create mode 100644 tests/benchmarks/qserialport/qserialport.pro create mode 100644 tests/benchmarks/qserialport/tst_qserialport.cpp diff --git a/tests/benchmarks/benchmarks.pro b/tests/benchmarks/benchmarks.pro new file mode 100644 index 00000000..8878128b --- /dev/null +++ b/tests/benchmarks/benchmarks.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS = qserialport diff --git a/tests/benchmarks/qserialport/qserialport.pro b/tests/benchmarks/qserialport/qserialport.pro new file mode 100644 index 00000000..c16cd5ee --- /dev/null +++ b/tests/benchmarks/qserialport/qserialport.pro @@ -0,0 +1,11 @@ +QT = core testlib +TARGET = tst_qserialport +#CONFIG += testcase + +greaterThan(QT_MAJOR_VERSION, 4) { + QT += serialport +} else { + include($$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf) +} + +SOURCES = tst_qserialport.cpp diff --git a/tests/benchmarks/qserialport/tst_qserialport.cpp b/tests/benchmarks/qserialport/tst_qserialport.cpp new file mode 100644 index 00000000..0ff20506 --- /dev/null +++ b/tests/benchmarks/qserialport/tst_qserialport.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Denis Shienkov +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +class tst_QSerialPort : public QObject +{ + Q_OBJECT +public: + explicit tst_QSerialPort(); + + 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; + } + +private slots: + void initTestCase(); + + void synchronousLoopbackDataVerificationTest(); + +private: +#ifdef Q_OS_WIN + void clearReceiver(); +#endif + + QString m_senderPortName; + QString m_receiverPortName; + + static int loopLevel; +}; + +int tst_QSerialPort::loopLevel = 0; + +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")); + m_receiverPortName = QString::fromLocal8Bit(qgetenv("QTEST_SERIALPORT_RECEIVER")); + if (m_senderPortName.isEmpty() || m_receiverPortName.isEmpty()) { +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + QSKIP("Test doesn't work because the names of serial ports aren't found in env."); +#else + QSKIP("Test doesn't work because the names of serial ports aren't set found env.", SkipAll); +#endif + } +} + +void tst_QSerialPort::synchronousLoopbackDataVerificationTest() +{ +#ifdef Q_OS_WIN + clearReceiver(); +#endif + + QSerialPort senderPort(m_senderPortName); + QVERIFY(senderPort.open(QSerialPort::WriteOnly)); + + QSerialPort receiverPort(m_receiverPortName); + QVERIFY(receiverPort.open(QSerialPort::ReadOnly)); + + QByteArray writeData; + for (int i = 0; i < 1024; ++i) + writeData.append(static_cast(i)); + + senderPort.write(writeData); + senderPort.waitForBytesWritten(-1); + + QByteArray readData; + while ((readData.size() < writeData.size()) && receiverPort.waitForReadyRead(100)) + readData.append(receiverPort.readAll()); + + QCOMPARE(writeData, readData); +} + +QTEST_MAIN(tst_QSerialPort) +#include "tst_qserialport.moc" diff --git a/tests/tests.pro b/tests/tests.pro index dcc85316..dc3e10c2 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -SUBDIRS += auto manual +SUBDIRS += auto manual benchmarks -- cgit v1.2.3 From 26504a5fe1c13af3b84b60eb2a5eb754c80d3c22 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Sat, 26 Jul 2014 01:31:28 +0400 Subject: Fix events handling in waitForBytesWritten() method on Windows In case of communication event is triggered in the waitForBytesWritten() method then necessary to process it with the _q_completeAsyncCommunication() method, but not with the _q_completeAsyncRead() method. Otherwise it leads to false filling of the readBuffer with the data that were read earlier (or with garbage) which remained in readChunkBuffer. The synchronous loopback autotest reproduces a bug without of this patch. Tested on Windows 7/8 with the on-board and USB serial ports, using Qt5. Task-number: QTBUG-40344 Change-Id: I679109b60f4058c4c6f7e5f02c1f70ba6039d8d8 Reviewed-by: Sergey Belyashov --- src/serialport/qserialport_win.cpp | 6 ++-- tests/auto/qserialport/tst_qserialport.cpp | 51 ++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 3432fc94..a6e1df70 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -449,8 +449,10 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs) return false; } - if (triggeredEvent == communicationOverlapped.hEvent - || triggeredEvent == readCompletionOverlapped.hEvent) { + if (triggeredEvent == communicationOverlapped.hEvent) { + if (!_q_completeAsyncCommunication()) + return false; + } else if (triggeredEvent == readCompletionOverlapped.hEvent) { if (!_q_completeAsyncRead()) return false; } else if (triggeredEvent == writeCompletionOverlapped.hEvent) { diff --git a/tests/auto/qserialport/tst_qserialport.cpp b/tests/auto/qserialport/tst_qserialport.cpp index 192541ce..4709d134 100644 --- a/tests/auto/qserialport/tst_qserialport.cpp +++ b/tests/auto/qserialport/tst_qserialport.cpp @@ -104,13 +104,15 @@ private slots: void waitForReadyReadWithOneByte(); void waitForReadyReadWithAlphabet(); + void twoStageSynchronousLoopback(); + protected slots: void handleBytesWrittenAndExitLoopSlot(qint64 bytesWritten); void handleBytesWrittenAndExitLoopSlot2(qint64 bytesWritten); private: #ifdef Q_OS_WIN - void clearReceiver(); + void clearReceiver(const QString &customReceiverName = QString()); #endif QString m_senderPortName; @@ -142,9 +144,10 @@ tst_QSerialPort::tst_QSerialPort() // 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() +void tst_QSerialPort::clearReceiver(const QString &customReceiverName) { - QSerialPort receiver(m_receiverPortName); + QSerialPort receiver(customReceiverName.isEmpty() + ? m_receiverPortName : customReceiverName); if (receiver.open(QIODevice::ReadOnly)) enterLoopMsecs(100); } @@ -438,5 +441,47 @@ void tst_QSerialPort::waitForReadyReadWithAlphabet() QVERIFY(readyReadSpy.count() > 0); } +void tst_QSerialPort::twoStageSynchronousLoopback() +{ +#ifdef Q_OS_WIN + clearReceiver(); + clearReceiver(m_senderPortName); +#endif + + QSerialPort senderPort(m_senderPortName); + QVERIFY(senderPort.open(QSerialPort::ReadWrite)); + + QSerialPort receiverPort(m_receiverPortName); + QVERIFY(receiverPort.open(QSerialPort::ReadWrite)); + + const int waitMsecs = 50; + + // first stage + senderPort.write(newlineArray); + senderPort.waitForBytesWritten(waitMsecs); + QTest::qSleep(waitMsecs); + receiverPort.waitForReadyRead(waitMsecs); + QCOMPARE(newlineArray.size(), receiverPort.bytesAvailable()); + receiverPort.write(receiverPort.readAll()); + receiverPort.waitForBytesWritten(waitMsecs); + QTest::qSleep(waitMsecs); + senderPort.waitForReadyRead(waitMsecs); + QCOMPARE(newlineArray.size(), senderPort.bytesAvailable()); + QCOMPARE(newlineArray, senderPort.readAll()); + + // second stage + senderPort.write(newlineArray); + senderPort.waitForBytesWritten(waitMsecs); + QTest::qSleep(waitMsecs); + receiverPort.waitForReadyRead(waitMsecs); + QCOMPARE(newlineArray.size(), receiverPort.bytesAvailable()); + receiverPort.write(receiverPort.readAll()); + receiverPort.waitForBytesWritten(waitMsecs); + QTest::qSleep(waitMsecs); + senderPort.waitForReadyRead(waitMsecs); + QCOMPARE(newlineArray.size(), senderPort.bytesAvailable()); + QCOMPARE(newlineArray, senderPort.readAll()); +} + QTEST_MAIN(tst_QSerialPort) #include "tst_qserialport.moc" -- cgit v1.2.3 From 5002109313f914674d20a2fac1c38ce5360fb67d Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Fri, 25 Jul 2014 12:14:54 +0400 Subject: Fix leak of a descriptor after unsuccessful opening In case of unsuccessful initialization of a device at the opening, a valid descriptor has to be closed before return from the open() method. Task-number: QTBUG-40414 Change-Id: I45568f176e003d9be1fe8c3017da29f39908efb0 Reviewed-by: Sergey Belyashov --- src/serialport/qserialport_unix.cpp | 72 +++++++++++++---------- src/serialport/qserialport_unix_p.h | 1 + src/serialport/qserialport_win.cpp | 109 +++++++++++++++++++---------------- src/serialport/qserialport_win_p.h | 1 + src/serialport/qserialport_wince.cpp | 83 ++++++++++++++------------ src/serialport/qserialport_wince_p.h | 1 + 6 files changed, 152 insertions(+), 115 deletions(-) diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index 29822d51..11ab16f2 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -204,39 +204,11 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) return false; } -#ifdef TIOCEXCL - if (::ioctl(descriptor, TIOCEXCL) == -1) - q->setError(decodeSystemError()); -#endif - - if (::tcgetattr(descriptor, &restoredTermios) == -1) { - q->setError(decodeSystemError()); + if (!initialize(mode)) { + qt_safe_close(descriptor); return false; } - currentTermios = restoredTermios; -#ifdef Q_OS_SOLARIS - currentTermios.c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); - currentTermios.c_oflag &= ~OPOST; - currentTermios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); - currentTermios.c_cflag &= ~(CSIZE|PARENB); - currentTermios.c_cflag |= CS8; -#else - ::cfmakeraw(¤tTermios); -#endif - currentTermios.c_cflag |= CLOCAL; - currentTermios.c_cc[VTIME] = 0; - currentTermios.c_cc[VMIN] = 0; - - if (mode & QIODevice::ReadOnly) - currentTermios.c_cflag |= CREAD; - - if (!updateTermios()) - return false; - - if ((flags & O_WRONLY) == 0) - setReadNotificationEnabled(true); - lockFileScopedPointer.swap(newLockFileScopedPointer); return true; @@ -869,6 +841,46 @@ bool QSerialPortPrivate::completeAsyncWrite() return startAsyncWrite(); } +inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode) +{ + Q_Q(QSerialPort); + +#ifdef TIOCEXCL + if (::ioctl(descriptor, TIOCEXCL) == -1) + q->setError(decodeSystemError()); +#endif + + if (::tcgetattr(descriptor, &restoredTermios) == -1) { + q->setError(decodeSystemError()); + return false; + } + + currentTermios = restoredTermios; +#ifdef Q_OS_SOLARIS + currentTermios.c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + currentTermios.c_oflag &= ~OPOST; + currentTermios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + currentTermios.c_cflag &= ~(CSIZE|PARENB); + currentTermios.c_cflag |= CS8; +#else + ::cfmakeraw(¤tTermios); +#endif + currentTermios.c_cflag |= CLOCAL; + currentTermios.c_cc[VTIME] = 0; + currentTermios.c_cc[VMIN] = 0; + + if (mode & QIODevice::ReadOnly) + currentTermios.c_cflag |= CREAD; + + if (!updateTermios()) + return false; + + if (mode & QIODevice::ReadOnly) + setReadNotificationEnabled(true); + + return true; +} + bool QSerialPortPrivate::updateTermios() { Q_Q(QSerialPort); diff --git a/src/serialport/qserialport_unix_p.h b/src/serialport/qserialport_unix_p.h index 64d1d9ec..ee3d82d5 100644 --- a/src/serialport/qserialport_unix_p.h +++ b/src/serialport/qserialport_unix_p.h @@ -153,6 +153,7 @@ public: QScopedPointer lockFileScopedPointer; private: + bool initialize(QIODevice::OpenMode mode); bool updateTermios(); QSerialPort::SerialPortError setBaudRate_helper(qint32 baudRate, diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index a6e1df70..eccaca90 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -155,56 +155,11 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) return false; } - ::ZeroMemory(&restoredDcb, sizeof(restoredDcb)); - restoredDcb.DCBlength = sizeof(restoredDcb); - - if (!::GetCommState(handle, &restoredDcb)) { - q->setError(decodeSystemError()); - return false; - } - - currentDcb = restoredDcb; - currentDcb.fBinary = TRUE; - currentDcb.fInX = FALSE; - currentDcb.fOutX = FALSE; - currentDcb.fAbortOnError = FALSE; - currentDcb.fNull = FALSE; - currentDcb.fErrorChar = FALSE; - - if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE) - currentDcb.fDtrControl = DTR_CONTROL_DISABLE; - - if (!updateDcb()) - return false; - - if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) { - q->setError(decodeSystemError()); - return false; - } - - ::ZeroMemory(¤tCommTimeouts, sizeof(currentCommTimeouts)); - currentCommTimeouts.ReadIntervalTimeout = MAXDWORD; - - if (!updateCommTimeouts()) - return false; - - if (mode & QIODevice::ReadOnly) - readCompletionNotifier->setEnabled(true); - - if (mode & QIODevice::WriteOnly) - writeCompletionNotifier->setEnabled(true); - - if (!::SetCommMask(handle, originalEventMask)) { - q->setError(decodeSystemError()); - return false; - } - - if (!startAsyncCommunication()) - return false; - - communicationNotifier->setEnabled(true); + if (initialize(mode)) + return true; - return true; + ::CloseHandle(handle); + return false; } void QSerialPortPrivate::close() @@ -743,6 +698,62 @@ void QSerialPortPrivate::handleLineStatusErrors() } } +inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode) +{ + Q_Q(QSerialPort); + + ::ZeroMemory(&restoredDcb, sizeof(restoredDcb)); + restoredDcb.DCBlength = sizeof(restoredDcb); + + if (!::GetCommState(handle, &restoredDcb)) { + q->setError(decodeSystemError()); + return false; + } + + currentDcb = restoredDcb; + currentDcb.fBinary = TRUE; + currentDcb.fInX = FALSE; + currentDcb.fOutX = FALSE; + currentDcb.fAbortOnError = FALSE; + currentDcb.fNull = FALSE; + currentDcb.fErrorChar = FALSE; + + if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE) + currentDcb.fDtrControl = DTR_CONTROL_DISABLE; + + if (!updateDcb()) + return false; + + if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) { + q->setError(decodeSystemError()); + return false; + } + + ::ZeroMemory(¤tCommTimeouts, sizeof(currentCommTimeouts)); + currentCommTimeouts.ReadIntervalTimeout = MAXDWORD; + + if (!updateCommTimeouts()) + return false; + + if (mode & QIODevice::ReadOnly) + readCompletionNotifier->setEnabled(true); + + if (mode & QIODevice::WriteOnly) + writeCompletionNotifier->setEnabled(true); + + if (!::SetCommMask(handle, originalEventMask)) { + q->setError(decodeSystemError()); + return false; + } + + if (!startAsyncCommunication()) + return false; + + communicationNotifier->setEnabled(true); + + return true; +} + bool QSerialPortPrivate::updateDcb() { Q_Q(QSerialPort); diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h index daf57884..a997315b 100644 --- a/src/serialport/qserialport_win_p.h +++ b/src/serialport/qserialport_win_p.h @@ -130,6 +130,7 @@ public: DWORD triggeredEventMask; private: + bool initialize(QIODevice::OpenMode mode); bool updateDcb(); bool updateCommTimeouts(); qint64 handleOverlappedResult(int direction, OVERLAPPED &overlapped); diff --git a/src/serialport/qserialport_wince.cpp b/src/serialport/qserialport_wince.cpp index 4a523ae6..c06e748c 100644 --- a/src/serialport/qserialport_wince.cpp +++ b/src/serialport/qserialport_wince.cpp @@ -219,43 +219,11 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) return false; } - ::ZeroMemory(&restoredDcb, sizeof(restoredDcb)); - restoredDcb.DCBlength = sizeof(restoredDcb); - - if (!::GetCommState(handle, &restoredDcb)) { - q->setError(decodeSystemError()); - return false; - } - - currentDcb = restoredDcb; - currentDcb.fBinary = true; - currentDcb.fInX = false; - currentDcb.fOutX = false; - currentDcb.fAbortOnError = false; - currentDcb.fNull = false; - currentDcb.fErrorChar = false; - - if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE) - currentDcb.fDtrControl = DTR_CONTROL_DISABLE; - - if (!updateDcb()) - return false; - - if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) { - q->setError(decodeSystemError()); - return false; - } - - ::memset(¤tCommTimeouts, 0, sizeof(currentCommTimeouts)); - currentCommTimeouts.ReadIntervalTimeout = MAXDWORD; - - if (!updateCommTimeouts()) - return false; - - eventNotifier = new CommEventNotifier(eventMask, this, q); - eventNotifier->start(); + if (initialize(eventMask)) + return true; - return true; + ::CloseHandle(handle); + return false; } void QSerialPortPrivate::close() @@ -646,6 +614,49 @@ void QSerialPortPrivate::processIoErrors(bool error) } } +inline bool QSerialPortPrivate::initialize(DWORD eventMask) +{ + Q_Q(QSerialPort); + + ::ZeroMemory(&restoredDcb, sizeof(restoredDcb)); + restoredDcb.DCBlength = sizeof(restoredDcb); + + if (!::GetCommState(handle, &restoredDcb)) { + q->setError(decodeSystemError()); + return false; + } + + currentDcb = restoredDcb; + currentDcb.fBinary = true; + currentDcb.fInX = false; + currentDcb.fOutX = false; + currentDcb.fAbortOnError = false; + currentDcb.fNull = false; + currentDcb.fErrorChar = false; + + if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE) + currentDcb.fDtrControl = DTR_CONTROL_DISABLE; + + if (!updateDcb()) + return false; + + if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) { + q->setError(decodeSystemError()); + return false; + } + + ::memset(¤tCommTimeouts, 0, sizeof(currentCommTimeouts)); + currentCommTimeouts.ReadIntervalTimeout = MAXDWORD; + + if (!updateCommTimeouts()) + return false; + + eventNotifier = new CommEventNotifier(eventMask, this, q); + eventNotifier->start(); + + return true; +} + bool QSerialPortPrivate::updateDcb() { Q_Q(QSerialPort); diff --git a/src/serialport/qserialport_wince_p.h b/src/serialport/qserialport_wince_p.h index 11d05345..9697dc72 100644 --- a/src/serialport/qserialport_wince_p.h +++ b/src/serialport/qserialport_wince_p.h @@ -112,6 +112,7 @@ public: QMutex settingsChangeMutex; private: + bool initialize(DWORD eventMask); bool updateDcb(); bool updateCommTimeouts(); -- cgit v1.2.3 From 72c6169b21793da91b3e652ae5f1e21c45c067d3 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 10 Jul 2014 16:46:28 +0400 Subject: Pass a length of string to QString::fromWCharArray Using of the QString::fromWCharArray() we didn't pass length of a string, hoping that all WCHAR strings are terminated by the null-character. But it can lead to the wrong results if the initial WCHAR string has no null character. Therefore it is reasonable to pass length of a string to exclude an error. Besides, to do not break of the algorithm of string comparison it is necessary to return not null-terminated strings. Also now there is no need to initialize of some allocated arrays by zero values. Tested on Windows 7/8 with the on-board, the virtual com0com, the USB FTDI and the PL2303 serial ports, using Qt4 and then Qt5. Change-Id: I382cf8eacf4ab4d21c54de17fcdd6b9fcfa3d02c Reviewed-by: Konstantin Ritt Reviewed-by: Denis Shienkov --- src/serialport/qserialportinfo_win.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp index 0e01ac72..8250d2a7 100644 --- a/src/serialport/qserialportinfo_win.cpp +++ b/src/serialport/qserialportinfo_win.cpp @@ -71,6 +71,15 @@ static inline const QList& guidFlagsPairs() return guidFlagsPairList; } +static QString toStringAndTrimNullCharacter(const QByteArray &buffer) +{ + QString result = QString::fromWCharArray(reinterpret_cast(buffer.constData()), + buffer.size() / sizeof(wchar_t)); + while (!result.isEmpty() && (result.at(result.size() - 1).unicode() == 0)) + result.chop(1); + return result; +} + static QStringList portNamesFromHardwareDeviceMap() { HKEY hKey = 0; @@ -80,7 +89,8 @@ static QStringList portNamesFromHardwareDeviceMap() QStringList result; DWORD index = 0; static const DWORD maximumValueNameInChars = 16383; - QByteArray outputValueName(maximumValueNameInChars * sizeof(wchar_t), 0); + QByteArray outputValueName; + outputValueName.resize(maximumValueNameInChars * sizeof(wchar_t)); QByteArray outputBuffer; DWORD requiredDataBytes = 0; forever { @@ -90,7 +100,7 @@ static QStringList portNamesFromHardwareDeviceMap() if (ret == ERROR_MORE_DATA) { outputBuffer.resize(requiredDataBytes); } else if (ret == ERROR_SUCCESS) { - result.append(QString::fromWCharArray(reinterpret_cast(outputBuffer.constData()))); + result.append(toStringAndTrimNullCharacter(outputBuffer)); ++index; } else { break; @@ -120,7 +130,7 @@ static QString deviceRegistryProperty(HDEVINFO deviceInfoSet, } devicePropertyByteArray.resize(requiredSize); } - return QString::fromWCharArray(reinterpret_cast(devicePropertyByteArray.constData())); + return toStringAndTrimNullCharacter(devicePropertyByteArray); } static QString deviceInstanceIdentifier(DEVINST deviceInstanceNumber) @@ -130,12 +140,13 @@ static QString deviceInstanceIdentifier(DEVINST deviceInstanceNumber) return QString(); // The size does not include the terminating null character. ++numberOfChars; - QByteArray outputBuffer(numberOfChars * sizeof(wchar_t), 0); + QByteArray outputBuffer; + outputBuffer.resize(numberOfChars * sizeof(wchar_t)); if (::CM_Get_Device_ID(deviceInstanceNumber, reinterpret_cast(outputBuffer.data()), outputBuffer.size(), 0) != CR_SUCCESS) { return QString(); } - return QString::fromWCharArray(reinterpret_cast(outputBuffer.constData())); + return toStringAndTrimNullCharacter(outputBuffer); } static DEVINST parentDeviceInstanceNumber(DEVINST childDeviceInstanceNumber) @@ -176,7 +187,7 @@ static QString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInf continue; } else if (ret == ERROR_SUCCESS) { if (dataType == REG_SZ) - portName = QString::fromWCharArray((reinterpret_cast(outputBuffer.constData()))); + portName = toStringAndTrimNullCharacter(outputBuffer); else if (dataType == REG_DWORD) portName = QStringLiteral("COM%1").arg(*(PDWORD(outputBuffer.constData()))); } -- cgit v1.2.3 From d402b2cd84fc55c6c9399bb4fc9e1ad764c07cde Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Sat, 19 Jul 2014 19:53:16 +0400 Subject: Make the QSerialPort::flush() non-blocking According to documentation, the flush() method shall be non-blocking. Tested on Linux 64-bit with auto-tests with the on-board and the USB serial ports for Qt4 and then Qt5. Note: On Windows the flush() method still does not work. Change-Id: Iaee80361e59e0c281206ca24c817a446cdbf6ed1 Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialport_unix.cpp | 7 +------ src/serialport/qserialport_win.cpp | 15 +-------------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index 11ab16f2..d555805c 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -337,12 +337,7 @@ bool QSerialPortPrivate::setRequestToSend(bool set) bool QSerialPortPrivate::flush() { - return completeAsyncWrite() -#ifndef Q_OS_ANDROID - && (::tcdrain(descriptor) != -1); -#else - && (::ioctl(descriptor, TCSBRK, 1) != -1); -#endif + return completeAsyncWrite(); } bool QSerialPortPrivate::clear(QSerialPort::Directions directions) diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index eccaca90..19f35b74 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -259,20 +259,7 @@ bool QSerialPortPrivate::setRequestToSend(bool set) bool QSerialPortPrivate::flush() { - Q_Q(QSerialPort); - - bool returnValue = true; - - if (!startAsyncWrite()) - returnValue = false; - - if (!::FlushFileBuffers(handle)) { - q->setError(decodeSystemError()); - returnValue = false; - } - - return returnValue; - + return startAsyncWrite(); } bool QSerialPortPrivate::clear(QSerialPort::Directions directions) -- cgit v1.2.3 From 1be34e49c2255625f317415ffcaaa27ba6ff0cdf Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Sat, 26 Jul 2014 17:55:43 +0400 Subject: Move the synchronous loopback test from benchmarks to auto tests Previous commit 76f293bfb0fd7bab391f96ac822eacc40e4c5176 with adding of this test to the benchmarks were hasty. After all it makes sense to place it to auto tests to have opportunity to run with others together. Besides, this test is renamed since it is not a loopback, it is an I/O test with the synchronous approach. Change-Id: I043a6e0075561167bb29a59a384554ef98dbbd4a Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- tests/auto/qserialport/tst_qserialport.cpp | 28 +++++ tests/benchmarks/benchmarks.pro | 2 - tests/benchmarks/qserialport/qserialport.pro | 11 -- tests/benchmarks/qserialport/tst_qserialport.cpp | 144 ----------------------- tests/tests.pro | 2 +- 5 files changed, 29 insertions(+), 158 deletions(-) delete mode 100644 tests/benchmarks/benchmarks.pro delete mode 100644 tests/benchmarks/qserialport/qserialport.pro delete mode 100644 tests/benchmarks/qserialport/tst_qserialport.cpp diff --git a/tests/auto/qserialport/tst_qserialport.cpp b/tests/auto/qserialport/tst_qserialport.cpp index 4709d134..9e8f6594 100644 --- a/tests/auto/qserialport/tst_qserialport.cpp +++ b/tests/auto/qserialport/tst_qserialport.cpp @@ -106,6 +106,8 @@ private slots: void twoStageSynchronousLoopback(); + void synchronousReadWrite(); + protected slots: void handleBytesWrittenAndExitLoopSlot(qint64 bytesWritten); void handleBytesWrittenAndExitLoopSlot2(qint64 bytesWritten); @@ -483,5 +485,31 @@ void tst_QSerialPort::twoStageSynchronousLoopback() QCOMPARE(newlineArray, senderPort.readAll()); } +void tst_QSerialPort::synchronousReadWrite() +{ +#ifdef Q_OS_WIN + clearReceiver(); +#endif + + QSerialPort senderPort(m_senderPortName); + QVERIFY(senderPort.open(QSerialPort::WriteOnly)); + + QSerialPort receiverPort(m_receiverPortName); + QVERIFY(receiverPort.open(QSerialPort::ReadOnly)); + + QByteArray writeData; + for (int i = 0; i < 1024; ++i) + writeData.append(static_cast(i)); + + senderPort.write(writeData); + senderPort.waitForBytesWritten(-1); + + QByteArray readData; + while ((readData.size() < writeData.size()) && receiverPort.waitForReadyRead(100)) + readData.append(receiverPort.readAll()); + + QCOMPARE(writeData, readData); +} + QTEST_MAIN(tst_QSerialPort) #include "tst_qserialport.moc" diff --git a/tests/benchmarks/benchmarks.pro b/tests/benchmarks/benchmarks.pro deleted file mode 100644 index 8878128b..00000000 --- a/tests/benchmarks/benchmarks.pro +++ /dev/null @@ -1,2 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = qserialport diff --git a/tests/benchmarks/qserialport/qserialport.pro b/tests/benchmarks/qserialport/qserialport.pro deleted file mode 100644 index c16cd5ee..00000000 --- a/tests/benchmarks/qserialport/qserialport.pro +++ /dev/null @@ -1,11 +0,0 @@ -QT = core testlib -TARGET = tst_qserialport -#CONFIG += testcase - -greaterThan(QT_MAJOR_VERSION, 4) { - QT += serialport -} else { - include($$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf) -} - -SOURCES = tst_qserialport.cpp diff --git a/tests/benchmarks/qserialport/tst_qserialport.cpp b/tests/benchmarks/qserialport/tst_qserialport.cpp deleted file mode 100644 index 0ff20506..00000000 --- a/tests/benchmarks/qserialport/tst_qserialport.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Denis Shienkov -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtSerialPort module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include - -class tst_QSerialPort : public QObject -{ - Q_OBJECT -public: - explicit tst_QSerialPort(); - - 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; - } - -private slots: - void initTestCase(); - - void synchronousLoopbackDataVerificationTest(); - -private: -#ifdef Q_OS_WIN - void clearReceiver(); -#endif - - QString m_senderPortName; - QString m_receiverPortName; - - static int loopLevel; -}; - -int tst_QSerialPort::loopLevel = 0; - -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")); - m_receiverPortName = QString::fromLocal8Bit(qgetenv("QTEST_SERIALPORT_RECEIVER")); - if (m_senderPortName.isEmpty() || m_receiverPortName.isEmpty()) { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) - QSKIP("Test doesn't work because the names of serial ports aren't found in env."); -#else - QSKIP("Test doesn't work because the names of serial ports aren't set found env.", SkipAll); -#endif - } -} - -void tst_QSerialPort::synchronousLoopbackDataVerificationTest() -{ -#ifdef Q_OS_WIN - clearReceiver(); -#endif - - QSerialPort senderPort(m_senderPortName); - QVERIFY(senderPort.open(QSerialPort::WriteOnly)); - - QSerialPort receiverPort(m_receiverPortName); - QVERIFY(receiverPort.open(QSerialPort::ReadOnly)); - - QByteArray writeData; - for (int i = 0; i < 1024; ++i) - writeData.append(static_cast(i)); - - senderPort.write(writeData); - senderPort.waitForBytesWritten(-1); - - QByteArray readData; - while ((readData.size() < writeData.size()) && receiverPort.waitForReadyRead(100)) - readData.append(receiverPort.readAll()); - - QCOMPARE(writeData, readData); -} - -QTEST_MAIN(tst_QSerialPort) -#include "tst_qserialport.moc" diff --git a/tests/tests.pro b/tests/tests.pro index dc3e10c2..dcc85316 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -SUBDIRS += auto manual benchmarks +SUBDIRS += auto manual -- cgit v1.2.3 From 3c3b23b32c6d4a9067363f758aaf4ff9819b7fd8 Mon Sep 17 00:00:00 2001 From: Marcel Krems Date: Mon, 11 Aug 2014 16:51:12 +0200 Subject: Fix compilation of apps with QT_DISABLE_DEPRECATED_BEFORE=0x050300 The enum is already marked as deprecated leading to this error: qserialport.h:267:46: error: no type named 'DataErrorPolicy' in 'QSerialPort' void dataErrorPolicyChanged(QSerialPort::DataErrorPolicy policy); ~~~~~~~~~~~~~^ Change-Id: I8d178f0d0921b8f5308183e1f09a4c8388448e26 Reviewed-by: Denis Shienkov --- src/serialport/qserialport.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h index 45b9bbff..d0f65b5e 100644 --- a/src/serialport/qserialport.h +++ b/src/serialport/qserialport.h @@ -263,7 +263,9 @@ Q_SIGNALS: void parityChanged(QSerialPort::Parity parity); void stopBitsChanged(QSerialPort::StopBits stopBits); void flowControlChanged(QSerialPort::FlowControl flowControl); +#if QT_DEPRECATED_SINCE(5, 2) void dataErrorPolicyChanged(QSerialPort::DataErrorPolicy policy); +#endif void dataTerminalReadyChanged(bool set); void requestToSendChanged(bool set); void error(QSerialPort::SerialPortError serialPortError); -- cgit v1.2.3