summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/io/qprocess
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-08-26 20:06:57 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-08-26 20:06:57 +0200
commitafab1546a7665bac2a8d7a6452e6aea46bfd2127 (patch)
treed616a7559c54a40e35a12b464f606774c9b0475b /tests/auto/corelib/io/qprocess
parent06b457c693f207e392d3021d77a0ab18cd78da92 (diff)
parent53ecaade10319ecc1d8115521ae6d8eba1ee55c1 (diff)
Merge remote-tracking branch 'origin/5.5' into 5.6
Conflicts: qmake/doc/snippets/code/doc_src_qmake-manual.pro qmake/doc/src/qmake-manual.qdoc src/corelib/io/qstorageinfo_unix.cpp src/corelib/tools/qbytearray.cpp src/widgets/kernel/qwidgetwindow.cpp tests/auto/corelib/io/qprocess/tst_qprocess.cpp tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp tests/auto/network/access/qnetworkreply/BLACKLIST Change-Id: I9efcd7e1cce1c394eed425c43aa6fce7d2edf31c
Diffstat (limited to 'tests/auto/corelib/io/qprocess')
-rw-r--r--tests/auto/corelib/io/qprocess/qprocess.pri1
-rw-r--r--tests/auto/corelib/io/qprocess/testProcessHang/main.cpp62
-rw-r--r--tests/auto/corelib/io/qprocess/testProcessHang/testProcessHang.pro4
-rw-r--r--tests/auto/corelib/io/qprocess/tst_qprocess.cpp165
4 files changed, 212 insertions, 20 deletions
diff --git a/tests/auto/corelib/io/qprocess/qprocess.pri b/tests/auto/corelib/io/qprocess/qprocess.pri
index 430251fbf1..a43c823846 100644
--- a/tests/auto/corelib/io/qprocess/qprocess.pri
+++ b/tests/auto/corelib/io/qprocess/qprocess.pri
@@ -4,6 +4,7 @@ SUBPROGRAMS = \
testProcessEcho2 \
testProcessEcho3 \
testProcessEnvironment \
+ testProcessHang \
testProcessNormal \
testProcessOutput \
testProcessDeadWhileReading \
diff --git a/tests/auto/corelib/io/qprocess/testProcessHang/main.cpp b/tests/auto/corelib/io/qprocess/testProcessHang/main.cpp
new file mode 100644
index 0000000000..e06502f738
--- /dev/null
+++ b/tests/auto/corelib/io/qprocess/testProcessHang/main.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Intel Corporation.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <stdio.h>
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+# include <windows.h>
+
+void sleepForever()
+{
+ ::Sleep(INFINITE);
+}
+#else
+# include <unistd.h>
+
+void sleepForever()
+{
+ ::pause();
+}
+#endif
+
+int main()
+{
+ puts("ready.");
+ fflush(stdout);
+ fprintf(stderr, "ready.\n");
+ fflush(stderr);
+
+ // sleep forever, simulating a hung application
+ sleepForever();
+ return 0;
+}
diff --git a/tests/auto/corelib/io/qprocess/testProcessHang/testProcessHang.pro b/tests/auto/corelib/io/qprocess/testProcessHang/testProcessHang.pro
new file mode 100644
index 0000000000..e236e05c7d
--- /dev/null
+++ b/tests/auto/corelib/io/qprocess/testProcessHang/testProcessHang.pro
@@ -0,0 +1,4 @@
+SOURCES = main.cpp
+CONFIG -= qt app_bundle
+CONFIG += console
+DESTDIR = ./
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index 0d4c53a7a9..caefc3fc21 100644
--- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -116,7 +117,8 @@ private slots:
void setStandardInputFile();
void setStandardOutputFile_data();
void setStandardOutputFile();
- void setStandardOutputFile2();
+ void setStandardOutputFileNullDevice();
+ void setStandardOutputFileAndWaitForBytesWritten();
void setStandardOutputProcess_data();
void setStandardOutputProcess();
void removeFileWhileProcessIsRunning();
@@ -150,6 +152,9 @@ private slots:
void onlyOneStartedSignal();
void finishProcessBeforeReadingDone();
void waitForStartedWithoutStart();
+ void startStopStartStop();
+ void startStopStartStopBuffers_data();
+ void startStopStartStopBuffers();
// keep these at the end, since they use lots of processes and sometimes
// caused obscure failures to occur in tests that followed them (esp. on the Mac)
@@ -1970,22 +1975,6 @@ void tst_QProcess::setStandardOutputFile_data()
<< true;
}
-#ifndef Q_OS_WINCE
-void tst_QProcess::setStandardOutputFile2()
-{
- static const char testdata[] = "Test data.";
-
- QProcess process;
- process.setStandardOutputFile(QProcess::nullDevice());
- process.start("testProcessEcho2/testProcessEcho2");
- process.write(testdata, sizeof testdata);
- QPROCESS_VERIFY(process,waitForFinished());
- QCOMPARE(process.bytesAvailable(), Q_INT64_C(0));
-
- QVERIFY(!QFileInfo(QProcess::nullDevice()).isFile());
-}
-#endif
-
void tst_QProcess::setStandardOutputFile()
{
static const char data[] = "Original data. ";
@@ -2034,6 +2023,40 @@ void tst_QProcess::setStandardOutputFile()
QCOMPARE(all.size(), expectedsize);
}
+
+void tst_QProcess::setStandardOutputFileNullDevice()
+{
+ static const char testdata[] = "Test data.";
+
+ QProcess process;
+ process.setStandardOutputFile(QProcess::nullDevice());
+ process.start("testProcessEcho2/testProcessEcho2");
+ process.write(testdata, sizeof testdata);
+ QPROCESS_VERIFY(process,waitForFinished());
+ QCOMPARE(process.bytesAvailable(), Q_INT64_C(0));
+
+ QVERIFY(!QFileInfo(QProcess::nullDevice()).isFile());
+}
+
+void tst_QProcess::setStandardOutputFileAndWaitForBytesWritten()
+{
+ static const char testdata[] = "Test data.";
+
+ QFile file("data");
+ QProcess process;
+ process.setStandardOutputFile(file.fileName());
+ process.start("testProcessEcho2/testProcessEcho2");
+ process.write(testdata, sizeof testdata);
+ process.waitForBytesWritten();
+ QPROCESS_VERIFY(process, waitForFinished());
+
+ // open the file again and verify the data
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ QByteArray all = file.readAll();
+ file.close();
+
+ QCOMPARE(all, QByteArray::fromRawData(testdata, sizeof testdata - 1));
+}
#endif
#ifndef Q_OS_WINCE
@@ -2041,17 +2064,19 @@ void tst_QProcess::setStandardOutputFile()
void tst_QProcess::setStandardOutputProcess_data()
{
QTest::addColumn<bool>("merged");
- QTest::newRow("separate") << false;
- QTest::newRow("merged") << true;
+ QTest::addColumn<bool>("waitForBytesWritten");
+ QTest::newRow("separate") << false << false;
+ QTest::newRow("separate with waitForBytesWritten") << false << true;
+ QTest::newRow("merged") << true << false;
}
void tst_QProcess::setStandardOutputProcess()
{
-
QProcess source;
QProcess sink;
QFETCH(bool, merged);
+ QFETCH(bool, waitForBytesWritten);
source.setReadChannelMode(merged ? QProcess::MergedChannels : QProcess::SeparateChannels);
source.setStandardOutputProcess(&sink);
@@ -2060,6 +2085,8 @@ void tst_QProcess::setStandardOutputProcess()
QByteArray data("Hello, World");
source.write(data);
+ if (waitForBytesWritten)
+ source.waitForBytesWritten();
source.closeWriteChannel();
QPROCESS_VERIFY(source, waitForFinished());
QPROCESS_VERIFY(sink, waitForFinished());
@@ -2333,12 +2360,110 @@ void tst_QProcess::finishProcessBeforeReadingDone()
QCOMPARE(lines.last(), QStringLiteral("10239 -this is a number"));
}
+//-----------------------------------------------------------------------------
void tst_QProcess::waitForStartedWithoutStart()
{
QProcess process;
QVERIFY(!process.waitForStarted(5000));
}
+//-----------------------------------------------------------------------------
+void tst_QProcess::startStopStartStop()
+{
+ // we actually do start-stop x 3 :-)
+ QProcess process;
+ process.start("testProcessNormal/testProcessNormal");
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitCode(), 0);
+
+ process.start("testExitCodes/testExitCodes", QStringList() << "1");
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitCode(), 1);
+
+ process.start("testProcessNormal/testProcessNormal");
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitCode(), 0);
+}
+
+//-----------------------------------------------------------------------------
+void tst_QProcess::startStopStartStopBuffers_data()
+{
+ QTest::addColumn<int>("channelMode1");
+ QTest::addColumn<int>("channelMode2");
+
+ QTest::newRow("separate-separate") << int(QProcess::SeparateChannels) << int(QProcess::SeparateChannels);
+ QTest::newRow("separate-merged") << int(QProcess::SeparateChannels) << int(QProcess::MergedChannels);
+ QTest::newRow("merged-separate") << int(QProcess::MergedChannels) << int(QProcess::SeparateChannels);
+ QTest::newRow("merged-merged") << int(QProcess::MergedChannels) << int(QProcess::MergedChannels);
+ QTest::newRow("merged-forwarded") << int(QProcess::MergedChannels) << int(QProcess::ForwardedChannels);
+}
+
+void tst_QProcess::startStopStartStopBuffers()
+{
+ QFETCH(int, channelMode1);
+ QFETCH(int, channelMode2);
+
+ QProcess process;
+ process.setProcessChannelMode(QProcess::ProcessChannelMode(channelMode1));
+ process.start("testProcessHang/testProcessHang");
+ QVERIFY2(process.waitForReadyRead(), process.errorString().toLocal8Bit());
+ if (channelMode1 == QProcess::SeparateChannels || channelMode1 == QProcess::ForwardedOutputChannel) {
+ process.setReadChannel(QProcess::StandardError);
+ if (process.bytesAvailable() == 0)
+ QVERIFY(process.waitForReadyRead());
+ process.setReadChannel(QProcess::StandardOutput);
+ }
+
+ // We want to test that the write buffer still has bytes after the child
+ // exiting. We do that by writing to a child process that never reads. We
+ // just have to write more data than a pipe can hold, so that even if
+ // QProcess finds the pipe writable (during waitForFinished() or in the
+ // QWindowsPipeWriter thread), some data will remain. The worst case I know
+ // of is Linux, which defaults to 64 kB of buffer.
+
+ process.write(QByteArray(128 * 1024, 'a'));
+ QVERIFY(process.bytesToWrite() > 0);
+ process.kill();
+
+ QVERIFY(process.waitForFinished());
+
+#ifndef Q_OS_WIN
+ // confirm that our buffers are still full
+ // Note: this doesn't work on Windows because our buffers are drained into
+ // QWindowsPipeWriter before being sent to the child process.
+ QVERIFY(process.bytesToWrite() > 0);
+ QVERIFY(process.bytesAvailable() > 0); // channelMode1 is not ForwardedChannels
+ if (channelMode1 == QProcess::SeparateChannels || channelMode1 == QProcess::ForwardedOutputChannel) {
+ process.setReadChannel(QProcess::StandardError);
+ QVERIFY(process.bytesAvailable() > 0);
+ process.setReadChannel(QProcess::StandardOutput);
+ }
+#endif
+
+ process.setProcessChannelMode(QProcess::ProcessChannelMode(channelMode2));
+ process.start("testProcessEcho2/testProcessEcho2", QIODevice::ReadWrite | QIODevice::Text);
+
+ // the buffers should now be empty
+ QCOMPARE(process.bytesToWrite(), qint64(0));
+ QCOMPARE(process.bytesAvailable(), qint64(0));
+ process.setReadChannel(QProcess::StandardError);
+ QCOMPARE(process.bytesAvailable(), qint64(0));
+ process.setReadChannel(QProcess::StandardOutput);
+
+ process.write("line3\n");
+ process.closeWriteChannel();
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitCode(), 0);
+
+ if (channelMode2 == QProcess::MergedChannels) {
+ QCOMPARE(process.readAll(), QByteArray("lliinnee33\n\n"));
+ } else if (channelMode2 != QProcess::ForwardedChannels) {
+ QCOMPARE(process.readAllStandardOutput(), QByteArray("line3\n"));
+ if (channelMode2 == QProcess::SeparateChannels)
+ QCOMPARE(process.readAllStandardError(), QByteArray("line3\n"));
+ }
+}
+
#endif //QT_NO_PROCESS
QTEST_MAIN(tst_QProcess)