diff options
author | axis <qt-info@nokia.com> | 2009-04-24 11:34:15 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2009-04-24 11:34:15 (GMT) |
commit | 8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76 (patch) | |
tree | a17e1a767a89542ab59907462206d7dcf2e504b2 /tests/auto/qprocess | |
download | Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.zip Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.gz Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.bz2 |
Long live Qt for S60!
Diffstat (limited to 'tests/auto/qprocess')
45 files changed, 3653 insertions, 0 deletions
diff --git a/tests/auto/qprocess/.gitignore b/tests/auto/qprocess/.gitignore new file mode 100644 index 0000000..a273810 --- /dev/null +++ b/tests/auto/qprocess/.gitignore @@ -0,0 +1,22 @@ +tst_qprocess +fileWriterProcess/fileWriterProcess +test Space In Name/ +testDetached/testDetached +testExitCodes/testExitCodes +testGuiProcess/testGuiProcess +testProcessCrash/testProcessCrash +testProcessDeadWhileReading/testProcessDeadWhileReading +testProcessEOF/testProcessEOF +testProcessEcho/testProcessEcho +testProcessEcho2/testProcessEcho2 +testProcessEcho3/testProcessEcho3 +testProcessEnvironment/testProcessEnvironment +testProcessLoopback/testProcessLoopback +testProcessNormal/testProcessNormal +testProcessOutput/testProcessOutput +testProcessSpacesArgs/nospace +testProcessSpacesArgs/one space +testProcessSpacesArgs/two space s +testSetWorkingDirectory/testSetWorkingDirectory +testSoftExit/testSoftExit +data diff --git a/tests/auto/qprocess/fileWriterProcess/fileWriterProcess.pro b/tests/auto/qprocess/fileWriterProcess/fileWriterProcess.pro new file mode 100644 index 0000000..c9f87ba --- /dev/null +++ b/tests/auto/qprocess/fileWriterProcess/fileWriterProcess.pro @@ -0,0 +1,10 @@ +SOURCES = main.cpp +CONFIG += console +CONFIG -= app_bundle +QT = core +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + + diff --git a/tests/auto/qprocess/fileWriterProcess/main.cpp b/tests/auto/qprocess/fileWriterProcess/main.cpp new file mode 100644 index 0000000..34c9cff --- /dev/null +++ b/tests/auto/qprocess/fileWriterProcess/main.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtCore> + +int main(int argc, char **argv) +{ + QCoreApplication ca(argc, argv); + QFile f; + f.open(stdin, QIODevice::ReadOnly); + QString input; + char buf[1024]; + qint64 len; + while ((len = f.read(buf, 1024)) > 0) + input += QByteArray(buf, len); + f.close(); + QFile f2("fileWriterProcess.txt"); + f2.open(QIODevice::WriteOnly | QIODevice::Truncate); + f2.write(input.toLatin1()); + f2.close(); + return 0; +} diff --git a/tests/auto/qprocess/qprocess.pro b/tests/auto/qprocess/qprocess.pro new file mode 100644 index 0000000..57d15ad --- /dev/null +++ b/tests/auto/qprocess/qprocess.pro @@ -0,0 +1,30 @@ +TEMPLATE = subdirs + +SUBDIRS = testProcessCrash \ + testProcessEcho \ + testProcessEcho2 \ + testProcessEcho3 \ + testProcessLoopback \ + testProcessNormal \ + testProcessOutput \ + testProcessDeadWhileReading \ + testProcessEOF \ + testProcessSpacesArgs/nospace.pro \ + testExitCodes \ + testSpaceInName \ + testGuiProcess \ + testDetached \ + fileWriterProcess \ + testSetWorkingDirectory + +!symbian: { +SUBDIRS +=testProcessSpacesArgs/onespace.pro \ + testProcessSpacesArgs/twospaces.pro \ + testSoftExit +} + +win32:!wince*:SUBDIRS+=testProcessEchoGui + +SUBDIRS += test + + diff --git a/tests/auto/qprocess/test/test.pro b/tests/auto/qprocess/test/test.pro new file mode 100644 index 0000000..82f91f8 --- /dev/null +++ b/tests/auto/qprocess/test/test.pro @@ -0,0 +1,68 @@ +load(qttest_p4) + +SOURCES += ../tst_qprocess.cpp +!wince*: { +TARGET = ../tst_qprocess + +win32: { + CONFIG(debug, debug|release) { + TARGET = ../../debug/tst_qprocess +} else { + TARGET = ../../release/tst_qprocess + } +} +} else { + TARGET = tst_qprocess +} + + + +QT = core + +!symbian: { + QT += network +} + +embedded: QT += gui + +wince*: { + addFiles.sources = \ + ../fileWriterProcess \ + "../test Space In Name" \ + ../testBatFiles \ + ../testDetached \ + ../testExitCodes \ + ../testGuiProcess \ + ../testProcessCrash \ + ../testProcessDeadWhileReading \ + ../testProcessEcho \ + ../testProcessEcho2 \ + ../testProcessEcho3 \ + ../testProcessEchoGui \ + ../testProcessEOF \ + ../testProcessLoopback \ + ../testProcessNormal \ + ../testProcessOutput \ + ../testProcessSpacesArgs \ + ../testSoftExit \ + ../testSpaceInName + + addFiles.path = \Program Files\tst_qprocess + DEPLOYMENT += addFiles +} + +symbian: { + binDep.sources = \ + fileWriterProcess.exe \ + testDetached.exe \ + testExitCodes.exe \ + testProcessCrash.exe \ + testProcessEcho.exe \ + testProcessNormal.exe \ + testProcessOutput.exe \ + nospace.exe \ + testSpaceInName.exe + binDep.path = \sys\bin + + DEPLOYMENT += binDep +} diff --git a/tests/auto/qprocess/testBatFiles/simple.bat b/tests/auto/qprocess/testBatFiles/simple.bat new file mode 100755 index 0000000..900f7ae --- /dev/null +++ b/tests/auto/qprocess/testBatFiles/simple.bat @@ -0,0 +1,2 @@ +@echo off +echo Hello
\ No newline at end of file diff --git a/tests/auto/qprocess/testBatFiles/with space.bat b/tests/auto/qprocess/testBatFiles/with space.bat new file mode 100755 index 0000000..900f7ae --- /dev/null +++ b/tests/auto/qprocess/testBatFiles/with space.bat @@ -0,0 +1,2 @@ +@echo off +echo Hello
\ No newline at end of file diff --git a/tests/auto/qprocess/testDetached/main.cpp b/tests/auto/qprocess/testDetached/main.cpp new file mode 100644 index 0000000..035929b --- /dev/null +++ b/tests/auto/qprocess/testDetached/main.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QCoreApplication> +#include <QDebug> +#include <QStringList> +#include <QFile> +#include <QDir> + +#include <stdio.h> + +#if defined(Q_OS_UNIX) +#include <sys/types.h> +#include <unistd.h> +#elif defined(Q_OS_WIN) +#include <windows.h> +#endif + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + QStringList args = app.arguments(); + if (args.count() != 2) { + fprintf(stderr, "Usage: testDetached filename.txt\n"); + return 128; + } + + QFile f(args.at(1)); + if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { + fprintf(stderr, "Cannot open %s for writing", qPrintable(f.fileName())); + return 1; + } + + f.write(QDir::currentPath().toUtf8()); + f.putChar('\n'); +#if defined(Q_OS_UNIX) + f.write(QByteArray::number(quint64(getpid()))); +#elif defined(Q_OS_WIN) + f.write(QByteArray::number(quint64(GetCurrentProcessId()))); +#endif + f.putChar('\n'); + + f.close(); + + return 0; +} diff --git a/tests/auto/qprocess/testDetached/testDetached.pro b/tests/auto/qprocess/testDetached/testDetached.pro new file mode 100644 index 0000000..319cfa6 --- /dev/null +++ b/tests/auto/qprocess/testDetached/testDetached.pro @@ -0,0 +1,10 @@ +SOURCES = main.cpp +QT = core +CONFIG += console +CONFIG -= app_bundle +INSTALLS = +DESTDIR = ./ + +symbian*: { +TARGET.EPOCSTACKSIZE =0x14000 +} diff --git a/tests/auto/qprocess/testExitCodes/main.cpp b/tests/auto/qprocess/testExitCodes/main.cpp new file mode 100644 index 0000000..477791f --- /dev/null +++ b/tests/auto/qprocess/testExitCodes/main.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <stdlib.h> +int main(int /* argc */, char **argv) +{ + return atoi(argv[1]); +} + diff --git a/tests/auto/qprocess/testExitCodes/testExitCodes.pro b/tests/auto/qprocess/testExitCodes/testExitCodes.pro new file mode 100644 index 0000000..b083718 --- /dev/null +++ b/tests/auto/qprocess/testExitCodes/testExitCodes.pro @@ -0,0 +1,5 @@ +SOURCES += main.cpp +CONFIG -= qt app_bundle +CONFIG += console + +DESTDIR = ./ diff --git a/tests/auto/qprocess/testGuiProcess/main.cpp b/tests/auto/qprocess/testGuiProcess/main.cpp new file mode 100644 index 0000000..63e6aa1 --- /dev/null +++ b/tests/auto/qprocess/testGuiProcess/main.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtGui> +#include <stdio.h> + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + QLabel label("This process is just waiting to die"); + label.show(); + + int c; + fgetc(stdin); // block until fed + + qDebug("Process is running"); + + return 0; +} diff --git a/tests/auto/qprocess/testGuiProcess/testGuiProcess.pro b/tests/auto/qprocess/testGuiProcess/testGuiProcess.pro new file mode 100644 index 0000000..15a9e8e --- /dev/null +++ b/tests/auto/qprocess/testGuiProcess/testGuiProcess.pro @@ -0,0 +1,4 @@ +SOURCES += main.cpp +CONFIG += console +DESTDIR = ./ + diff --git a/tests/auto/qprocess/testProcessCrash/main.cpp b/tests/auto/qprocess/testProcessCrash/main.cpp new file mode 100644 index 0000000..b3e8272 --- /dev/null +++ b/tests/auto/qprocess/testProcessCrash/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +struct Foo +{ + int i; +}; + +int main() +{ + *(char*)0 = 0; + Foo *f = 0; + return f->i; +} diff --git a/tests/auto/qprocess/testProcessCrash/testProcessCrash.pro b/tests/auto/qprocess/testProcessCrash/testProcessCrash.pro new file mode 100644 index 0000000..abd8167 --- /dev/null +++ b/tests/auto/qprocess/testProcessCrash/testProcessCrash.pro @@ -0,0 +1,8 @@ +SOURCES = main.cpp +CONFIG += console +CONFIG -= qt app_bundle + +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = diff --git a/tests/auto/qprocess/testProcessDeadWhileReading/main.cpp b/tests/auto/qprocess/testProcessDeadWhileReading/main.cpp new file mode 100644 index 0000000..f314dde --- /dev/null +++ b/tests/auto/qprocess/testProcessDeadWhileReading/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <stdio.h> + +int main() +{ + for (int i=0; i<10240; i++) + fprintf(stdout, "%d dead while reading\n", i); + fflush(stdout); + + return 0; +} diff --git a/tests/auto/qprocess/testProcessDeadWhileReading/testProcessDeadWhileReading.pro b/tests/auto/qprocess/testProcessDeadWhileReading/testProcessDeadWhileReading.pro new file mode 100644 index 0000000..2168ba5 --- /dev/null +++ b/tests/auto/qprocess/testProcessDeadWhileReading/testProcessDeadWhileReading.pro @@ -0,0 +1,10 @@ +SOURCES = main.cpp +CONFIG -= qt +CONFIG += console + +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + + diff --git a/tests/auto/qprocess/testProcessEOF/main.cpp b/tests/auto/qprocess/testProcessEOF/main.cpp new file mode 100644 index 0000000..30a0319 --- /dev/null +++ b/tests/auto/qprocess/testProcessEOF/main.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <stdio.h> +#include <string.h> + +int main() +{ + char buf[32]; + memset(buf, 0, sizeof(buf)); + + char *cptr = buf; + int c; + while (cptr != buf + 31 && (c = fgetc(stdin)) != EOF) + *cptr++ = (char) c; + + printf("%s", buf); + return 0; +} diff --git a/tests/auto/qprocess/testProcessEOF/testProcessEOF.pro b/tests/auto/qprocess/testProcessEOF/testProcessEOF.pro new file mode 100644 index 0000000..f406759 --- /dev/null +++ b/tests/auto/qprocess/testProcessEOF/testProcessEOF.pro @@ -0,0 +1,9 @@ +SOURCES = main.cpp +CONFIG -= qt app_bundle +CONFIG += console + +!win32-g++:win32:!equals(TEMPLATE_PREFIX, "vc"):QMAKE_CXXFLAGS += /GS- +DESTDIR = ./ + + + diff --git a/tests/auto/qprocess/testProcessEcho/main.cpp b/tests/auto/qprocess/testProcessEcho/main.cpp new file mode 100644 index 0000000..ed5e1ea --- /dev/null +++ b/tests/auto/qprocess/testProcessEcho/main.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <stdio.h> + +int main() +{ +#if defined(_WIN32_WCE) && defined(_X86_) + return 0; +#else + int c; + while ((c = fgetc(stdin)) != -1) { + if (c == '\0') + break; + fputc(c, stdout); + fflush(stdout); + } + return 0; +#endif +} diff --git a/tests/auto/qprocess/testProcessEcho/testProcessEcho.pro b/tests/auto/qprocess/testProcessEcho/testProcessEcho.pro new file mode 100644 index 0000000..a14c1fe --- /dev/null +++ b/tests/auto/qprocess/testProcessEcho/testProcessEcho.pro @@ -0,0 +1,8 @@ +SOURCES = main.cpp +CONFIG -= qt +CONFIG += console +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + diff --git a/tests/auto/qprocess/testProcessEcho2/main.cpp b/tests/auto/qprocess/testProcessEcho2/main.cpp new file mode 100644 index 0000000..2f2134d --- /dev/null +++ b/tests/auto/qprocess/testProcessEcho2/main.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <stdio.h> + +int main() +{ + int c; + while ((c = fgetc(stdin)) != -1) { + if (c == '\0') + break; + fputc(c, stdout); + fputc(c, stderr); + fflush(stdout); + fflush(stderr); + } + + return 0; +} diff --git a/tests/auto/qprocess/testProcessEcho2/testProcessEcho2.pro b/tests/auto/qprocess/testProcessEcho2/testProcessEcho2.pro new file mode 100644 index 0000000..d8a303a --- /dev/null +++ b/tests/auto/qprocess/testProcessEcho2/testProcessEcho2.pro @@ -0,0 +1,10 @@ +SOURCES = main.cpp +CONFIG -= qt +CONFIG += console +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + + + diff --git a/tests/auto/qprocess/testProcessEcho3/main.cpp b/tests/auto/qprocess/testProcessEcho3/main.cpp new file mode 100644 index 0000000..932939e --- /dev/null +++ b/tests/auto/qprocess/testProcessEcho3/main.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <stdio.h> + +int main() +{ + int c; + for (;;) { + c = fgetc(stdin); + if (c == '\0') + break; + if (c != -1) { + fputc(c, stdout); + fputc(c, stderr); + fflush(stdout); + fflush(stderr); + } + } + + return 0; +} diff --git a/tests/auto/qprocess/testProcessEcho3/testProcessEcho3.pro b/tests/auto/qprocess/testProcessEcho3/testProcessEcho3.pro new file mode 100644 index 0000000..3b8f2fb --- /dev/null +++ b/tests/auto/qprocess/testProcessEcho3/testProcessEcho3.pro @@ -0,0 +1,9 @@ +SOURCES = main.cpp +CONFIG -= qt +CONFIG += console +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + + diff --git a/tests/auto/qprocess/testProcessEchoGui/main_win.cpp b/tests/auto/qprocess/testProcessEchoGui/main_win.cpp new file mode 100644 index 0000000..0fab773 --- /dev/null +++ b/tests/auto/qprocess/testProcessEchoGui/main_win.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <windows.h> + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + + HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + + HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE); + + for (;;) { + + char c = 0; + DWORD read = 0; + if (!ReadFile(hStdin, &c, 1, &read, 0) || read == 0 || c == 'q' || c == '\0') + break; + DWORD wrote = 0; + WriteFile(hStdout, &c, 1, &wrote, 0); + WriteFile(hStderr, &c, 1, &wrote, 0); + } + return 0; +}
\ No newline at end of file diff --git a/tests/auto/qprocess/testProcessEchoGui/testProcessEchoGui.pro b/tests/auto/qprocess/testProcessEchoGui/testProcessEchoGui.pro new file mode 100644 index 0000000..b3be74c --- /dev/null +++ b/tests/auto/qprocess/testProcessEchoGui/testProcessEchoGui.pro @@ -0,0 +1,13 @@ +win32 { + SOURCES = main_win.cpp + !win32-borland:LIBS += -lUser32 +} + +CONFIG -= qt +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + + + diff --git a/tests/auto/qprocess/testProcessLoopback/main.cpp b/tests/auto/qprocess/testProcessLoopback/main.cpp new file mode 100644 index 0000000..af09f95 --- /dev/null +++ b/tests/auto/qprocess/testProcessLoopback/main.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <stdio.h> + +int main() +{ + char buffer[1024]; + for (;;) { + size_t num = fread(buffer, 1, sizeof(buffer), stdin); + if (num <= 0) + break; + fwrite(buffer, num, 1, stdout); + fflush(stdout); + } + + return 0; +} diff --git a/tests/auto/qprocess/testProcessLoopback/testProcessLoopback.pro b/tests/auto/qprocess/testProcessLoopback/testProcessLoopback.pro new file mode 100644 index 0000000..a14c1fe --- /dev/null +++ b/tests/auto/qprocess/testProcessLoopback/testProcessLoopback.pro @@ -0,0 +1,8 @@ +SOURCES = main.cpp +CONFIG -= qt +CONFIG += console +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + diff --git a/tests/auto/qprocess/testProcessNormal/main.cpp b/tests/auto/qprocess/testProcessNormal/main.cpp new file mode 100644 index 0000000..cbe1981 --- /dev/null +++ b/tests/auto/qprocess/testProcessNormal/main.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +int main() +{ + return 0; +} diff --git a/tests/auto/qprocess/testProcessNormal/testProcessNormal.pro b/tests/auto/qprocess/testProcessNormal/testProcessNormal.pro new file mode 100644 index 0000000..3c6a595 --- /dev/null +++ b/tests/auto/qprocess/testProcessNormal/testProcessNormal.pro @@ -0,0 +1,9 @@ +SOURCES = main.cpp +CONFIG += console +CONFIG -= qt app_bundle + +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + diff --git a/tests/auto/qprocess/testProcessOutput/main.cpp b/tests/auto/qprocess/testProcessOutput/main.cpp new file mode 100644 index 0000000..9656887 --- /dev/null +++ b/tests/auto/qprocess/testProcessOutput/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <stdio.h> + +int main() +{ +#if defined(__SYMBIAN32__) + // Printing to stdout messes up the out.txt, so open a file and print there. + FILE* file = fopen("c:\\logs\\qprocess_output_test.txt","w+"); + for (int i=0; i<200; i++) { + fprintf(file, "%d -this is a number\n", i); + fflush(file); + } + fclose(file); +#else +# if defined(_WIN32_WCE) + for (int i=0; i<240; i++) { +# else //fprintf Output is very slow on Windows CE/Symbian + for (int i=0; i<10240; i++) { +# endif + fprintf(stdout, "%d -this is a number\n", i); + fflush(stderr); + } +#endif + return 0; +} diff --git a/tests/auto/qprocess/testProcessOutput/testProcessOutput.pro b/tests/auto/qprocess/testProcessOutput/testProcessOutput.pro new file mode 100644 index 0000000..3b8f2fb --- /dev/null +++ b/tests/auto/qprocess/testProcessOutput/testProcessOutput.pro @@ -0,0 +1,9 @@ +SOURCES = main.cpp +CONFIG -= qt +CONFIG += console +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + + diff --git a/tests/auto/qprocess/testProcessSpacesArgs/main.cpp b/tests/auto/qprocess/testProcessSpacesArgs/main.cpp new file mode 100644 index 0000000..5b63bcb --- /dev/null +++ b/tests/auto/qprocess/testProcessSpacesArgs/main.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <stdio.h> + +int main(int argc, char ** argv) +{ +#if defined(__SYMBIAN32__) + // Printing to stdout messes up the out.txt, so open a file and print there. + FILE* file = fopen("c:\\logs\\qprocess_args_test.txt","w+"); + for (int i = 0; i < argc; ++i) { + if (i) + fprintf(file, "|"); + fprintf(file, argv[i]); + } + fclose(file); +#else + for (int i = 0; i < argc; ++i) { + if (i) + printf("|"); + printf(argv[i]); + } +#endif + return 0; +} diff --git a/tests/auto/qprocess/testProcessSpacesArgs/nospace.pro b/tests/auto/qprocess/testProcessSpacesArgs/nospace.pro new file mode 100644 index 0000000..f55f02e --- /dev/null +++ b/tests/auto/qprocess/testProcessSpacesArgs/nospace.pro @@ -0,0 +1,9 @@ +SOURCES = main.cpp +CONFIG -= qt app_bundle +CONFIG += console +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + + diff --git a/tests/auto/qprocess/testProcessSpacesArgs/onespace.pro b/tests/auto/qprocess/testProcessSpacesArgs/onespace.pro new file mode 100644 index 0000000..2a56a95 --- /dev/null +++ b/tests/auto/qprocess/testProcessSpacesArgs/onespace.pro @@ -0,0 +1,11 @@ +SOURCES = main.cpp +CONFIG -= qt app_bundle +CONFIG += console +DESTDIR = ./ + +TARGET = "one space" + +# no install rule for application used by test +INSTALLS = + + diff --git a/tests/auto/qprocess/testProcessSpacesArgs/twospaces.pro b/tests/auto/qprocess/testProcessSpacesArgs/twospaces.pro new file mode 100644 index 0000000..d7c74a6 --- /dev/null +++ b/tests/auto/qprocess/testProcessSpacesArgs/twospaces.pro @@ -0,0 +1,12 @@ +SOURCES = main.cpp +CONFIG -= qt app_bundle +CONFIG += console +DESTDIR = ./ + +TARGET = "two space s" + +# no install rule for application used by test +INSTALLS = + + + diff --git a/tests/auto/qprocess/testSetWorkingDirectory/main.cpp b/tests/auto/qprocess/testSetWorkingDirectory/main.cpp new file mode 100644 index 0000000..d4ff683 --- /dev/null +++ b/tests/auto/qprocess/testSetWorkingDirectory/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtCore> + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + QByteArray currentPath = QDir::currentPath().toLocal8Bit(); + fprintf(stdout, "%s", currentPath.constData()); + app.exit(); +} diff --git a/tests/auto/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro b/tests/auto/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro new file mode 100644 index 0000000..b723604 --- /dev/null +++ b/tests/auto/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro @@ -0,0 +1,7 @@ +SOURCES = main.cpp +CONFIG += console +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + diff --git a/tests/auto/qprocess/testSoftExit/main_unix.cpp b/tests/auto/qprocess/testSoftExit/main_unix.cpp new file mode 100644 index 0000000..d358ffd --- /dev/null +++ b/tests/auto/qprocess/testSoftExit/main_unix.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <sys/types.h> +#include <signal.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + struct sigaction noaction; + memset(&noaction, 0, sizeof(noaction)); + noaction.sa_handler = SIG_IGN; + ::sigaction(SIGTERM, &noaction, 0); + + printf("Ready\n"); + fflush(stdout); + + for (int i = 0; i < 5; ++i) + sleep(1); + return 0; +} diff --git a/tests/auto/qprocess/testSoftExit/main_win.cpp b/tests/auto/qprocess/testSoftExit/main_win.cpp new file mode 100644 index 0000000..93b31e4 --- /dev/null +++ b/tests/auto/qprocess/testSoftExit/main_win.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <windows.h> +#include <stdio.h> + +int main() +{ + printf("Ready\n"); + fflush(stdout); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) { + if (msg.message == WM_CLOSE) + PostQuitMessage(0); + } + + return msg.wParam; +} diff --git a/tests/auto/qprocess/testSoftExit/testSoftExit.pro b/tests/auto/qprocess/testSoftExit/testSoftExit.pro new file mode 100644 index 0000000..9220359 --- /dev/null +++ b/tests/auto/qprocess/testSoftExit/testSoftExit.pro @@ -0,0 +1,16 @@ +win32 { + SOURCES = main_win.cpp + !win32-borland:!wince*:LIBS += -lUser32 +} +unix { + SOURCES = main_unix.cpp +} + +CONFIG -= qt app_bundle +CONFIG += console +DESTDIR = ./ + +# no install rule for application used by test +INSTALLS = + + diff --git a/tests/auto/qprocess/testSpaceInName/main.cpp b/tests/auto/qprocess/testSpaceInName/main.cpp new file mode 100644 index 0000000..622bcdf --- /dev/null +++ b/tests/auto/qprocess/testSpaceInName/main.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <stdio.h> + +int main() +{ + int c; + while ((c = fgetc(stdin)) != -1) { + if (c == '\0') + break; + fputc(c, stdout); + fflush(stdout); + } + + return 0; +} diff --git a/tests/auto/qprocess/testSpaceInName/testSpaceInName.pro b/tests/auto/qprocess/testSpaceInName/testSpaceInName.pro new file mode 100644 index 0000000..913e868 --- /dev/null +++ b/tests/auto/qprocess/testSpaceInName/testSpaceInName.pro @@ -0,0 +1,13 @@ +SOURCES = main.cpp +CONFIG -= qt +CONFIG += console +DESTDIR = "../test Space In Name" + +mac { + CONFIG -= app_bundle +} + +# no install rule for application used by test +INSTALLS = + + diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp new file mode 100644 index 0000000..428cf41 --- /dev/null +++ b/tests/auto/qprocess/tst_qprocess.cpp @@ -0,0 +1,2223 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <QtCore/QProcess> +#include <QtCore/QDir> +#include <QtCore/QFile> +#include <QtCore/QThread> +#include <QtCore/QRegExp> +#include <QtCore/QDebug> +#include <QtCore/QMetaType> +#if !defined(Q_OS_SYMBIAN) +// Network test unnecessary? +#include <QtNetwork/QHostInfo> +#endif +#include <stdlib.h> + +#if defined(Q_OS_WIN) +#include <windows.h> +#endif + +//TESTED_CLASS= +//TESTED_FILES= + +Q_DECLARE_METATYPE(QList<QProcess::ExitStatus>); +Q_DECLARE_METATYPE(QProcess::ExitStatus); +Q_DECLARE_METATYPE(QProcess::ProcessState); + +#define QPROCESS_VERIFY(Process, Fn) \ +{ \ +const bool ret = Process.Fn; \ +if (ret == false) \ + qWarning("QProcess error: %d: %s", Process.error(), qPrintable(Process.errorString())); \ +QVERIFY(ret); \ +} + +class tst_QProcess : public QObject +{ + Q_OBJECT + +public: + tst_QProcess(); + virtual ~tst_QProcess(); + +public slots: + void init(); + void cleanup(); + +private slots: + void getSetCheck(); + void constructing(); + void simpleStart(); + void startDetached(); + void crashTest(); + void crashTest2(); + void echoTest_data(); + void echoTest(); + void echoTest2(); + void echoTest_performance(); +#if defined Q_OS_WIN + void echoTestGui(); + void batFiles_data(); + void batFiles(); +#endif + void exitStatus_data(); + void exitStatus(); + void loopBackTest(); + void readTimeoutAndThenCrash(); + void waitForFinished(); + void deadWhileReading(); + void restartProcessDeadlock(); + void closeWriteChannel(); + void closeReadChannel(); + void openModes(); + void emitReadyReadOnlyWhenNewDataArrives(); + void hardExit(); + void softExit(); + void softExitInSlots_data(); + void softExitInSlots(); + void mergedChannels(); + void forwardedChannels(); + void atEnd(); + void atEnd2(); + void processInAThread(); + void processesInMultipleThreads(); + void waitForFinishedWithTimeout(); + void waitForReadyReadInAReadyReadSlot(); + void waitForBytesWrittenInABytesWrittenSlot(); + void spaceArgsTest_data(); + void spaceArgsTest(); + void exitCodeTest(); + void systemEnvironment(); + void spaceInName(); + void lockupsInStartDetached(); + void waitForReadyReadForNonexistantProcess(); + void setStandardInputFile(); + void setStandardOutputFile_data(); + void setStandardOutputFile(); + void setStandardOutputProcess_data(); + void setStandardOutputProcess(); + void removeFileWhileProcessIsRunning(); + void fileWriterProcess(); + void detachedWorkingDirectoryAndPid(); + void switchReadChannels(); + void setWorkingDirectory(); + void startFinishStartFinish(); + + // 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) + void failToStart(); + void failToStartWithWait(); + void failToStartWithEventLoop(); + +protected slots: + void readFromProcess(); + void exitLoopSlot(); + void restartProcess(); + void waitForReadyReadInAReadyReadSlotSlot(); + void waitForBytesWrittenInABytesWrittenSlotSlot(); + +private: + QProcess *process; + qint64 bytesAvailable; +}; + +// Testing get/set functions +void tst_QProcess::getSetCheck() +{ + QProcess obj1; + // ProcessChannelMode QProcess::readChannelMode() + // void QProcess::setReadChannelMode(ProcessChannelMode) + obj1.setReadChannelMode(QProcess::ProcessChannelMode(QProcess::SeparateChannels)); + QCOMPARE(QProcess::ProcessChannelMode(QProcess::SeparateChannels), obj1.readChannelMode()); + obj1.setReadChannelMode(QProcess::ProcessChannelMode(QProcess::MergedChannels)); + QCOMPARE(QProcess::ProcessChannelMode(QProcess::MergedChannels), obj1.readChannelMode()); + obj1.setReadChannelMode(QProcess::ProcessChannelMode(QProcess::ForwardedChannels)); + QCOMPARE(QProcess::ProcessChannelMode(QProcess::ForwardedChannels), obj1.readChannelMode()); + + // ProcessChannel QProcess::readChannel() + // void QProcess::setReadChannel(ProcessChannel) + obj1.setReadChannel(QProcess::ProcessChannel(QProcess::StandardOutput)); + QCOMPARE(QProcess::ProcessChannel(QProcess::StandardOutput), obj1.readChannel()); + obj1.setReadChannel(QProcess::ProcessChannel(QProcess::StandardError)); + QCOMPARE(QProcess::ProcessChannel(QProcess::StandardError), obj1.readChannel()); +} + +tst_QProcess::tst_QProcess() +{ +} + +tst_QProcess::~tst_QProcess() +{ +} + +void tst_QProcess::init() +{ +#ifdef Q_OS_SYMBIAN + QString dirStr = QString::fromLatin1("c:\\logs"); + QDir dir; + if (!dir.exists(dirStr)) + dir.mkpath(dirStr); +#endif +} + +void tst_QProcess::cleanup() +{ +} + +//----------------------------------------------------------------------------- +void tst_QProcess::constructing() +{ + QProcess process; + QCOMPARE(process.readChannel(), QProcess::StandardOutput); + QCOMPARE(process.workingDirectory(), QString()); + QCOMPARE(process.environment(), QStringList()); + QCOMPARE(process.error(), QProcess::UnknownError); + QCOMPARE(process.state(), QProcess::NotRunning); + QCOMPARE(process.pid(), Q_PID(0)); + QCOMPARE(process.readAllStandardOutput(), QByteArray()); + QCOMPARE(process.readAllStandardError(), QByteArray()); + QCOMPARE(process.canReadLine(), false); + + // QIODevice + QCOMPARE(process.openMode(), QIODevice::NotOpen); + QVERIFY(!process.isOpen()); + QVERIFY(!process.isReadable()); + QVERIFY(!process.isWritable()); + QVERIFY(process.isSequential()); + QCOMPARE(process.pos(), qlonglong(0)); + QCOMPARE(process.size(), qlonglong(0)); + QVERIFY(process.atEnd()); + QCOMPARE(process.bytesAvailable(), qlonglong(0)); + QCOMPARE(process.bytesToWrite(), qlonglong(0)); + QVERIFY(!process.errorString().isEmpty()); + + char c; + QCOMPARE(process.read(&c, 1), qlonglong(-1)); + QCOMPARE(process.write(&c, 1), qlonglong(-1)); +} + +void tst_QProcess::simpleStart() +{ + qRegisterMetaType<QProcess::ProcessState>("QProcess::ProcessState"); + + process = new QProcess; + QSignalSpy spy(process, SIGNAL(stateChanged(QProcess::ProcessState))); + connect(process, SIGNAL(readyRead()), this, SLOT(readFromProcess())); + + /* valgrind dislike SUID binaries(those that have the `s'-flag set), which + * makes it fail to start the process. For this reason utilities like `ping' won't + * start, when the auto test is run through `valgrind'. */ + process->start("testProcessNormal/testProcessNormal"); + if (process->state() != QProcess::Starting) + QCOMPARE(process->state(), QProcess::Running); + QVERIFY(process->waitForStarted(5000)); + QCOMPARE(process->state(), QProcess::Running); +#if defined(Q_OS_WINCE) + // Note: This actually seems incorrect, it will only exit the while loop when finishing fails + while (process->waitForFinished(5000)) + { } +#elif defined(Q_OS_SYMBIAN) + QVERIFY(process->waitForFinished(5000)); +#else + while (process->waitForReadyRead(5000)) + { } +#endif + QCOMPARE(process->state(), QProcess::NotRunning); + + delete process; + process = 0; + + QCOMPARE(spy.count(), 3); + QCOMPARE(qVariantValue<QProcess::ProcessState>(spy.at(0).at(0)), QProcess::Starting); + QCOMPARE(qVariantValue<QProcess::ProcessState>(spy.at(1).at(0)), QProcess::Running); + QCOMPARE(qVariantValue<QProcess::ProcessState>(spy.at(2).at(0)), QProcess::NotRunning); +} +//----------------------------------------------------------------------------- +void tst_QProcess::startDetached() +{ +#if QT_VERSION >= 0x040200 + QProcess proc; + QVERIFY(proc.startDetached("testProcessNormal/testProcessNormal", + QStringList() << "arg1" << "arg2")); +#endif + QCOMPARE(QProcess::startDetached("nonexistingexe"), false); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::readFromProcess() +{ + int lines = 0; + while (process->canReadLine()) { + ++lines; + QByteArray line = process->readLine(); + } +} + +//----------------------------------------------------------------------------- +void tst_QProcess::crashTest() +{ + qRegisterMetaType<QProcess::ProcessState>("QProcess::ProcessState"); +#ifdef Q_OS_WIN + QSKIP("This test opens a crash dialog on Windows", SkipSingle); +#endif + process = new QProcess; + QSignalSpy stateSpy(process, SIGNAL(stateChanged(QProcess::ProcessState))); + process->start("testProcessCrash/testProcessCrash"); + QVERIFY(process->waitForStarted(5000)); + + qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError"); + qRegisterMetaType<QProcess::ProcessError>("QProcess::ExitStatus"); + + QSignalSpy spy(process, SIGNAL(error(QProcess::ProcessError))); + QSignalSpy spy2(process, SIGNAL(finished(int, QProcess::ExitStatus))); + + QVERIFY(process->waitForFinished(5000)); + + QCOMPARE(spy.count(), 1); + QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed); + + QCOMPARE(spy2.count(), 1); + QCOMPARE(*static_cast<const QProcess::ExitStatus *>(spy2.at(0).at(1).constData()), QProcess::CrashExit); + + QCOMPARE(process->exitStatus(), QProcess::CrashExit); + + delete process; + process = 0; + + QCOMPARE(stateSpy.count(), 3); + QCOMPARE(qVariantValue<QProcess::ProcessState>(stateSpy.at(0).at(0)), QProcess::Starting); + QCOMPARE(qVariantValue<QProcess::ProcessState>(stateSpy.at(1).at(0)), QProcess::Running); + QCOMPARE(qVariantValue<QProcess::ProcessState>(stateSpy.at(2).at(0)), QProcess::NotRunning); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::crashTest2() +{ +#ifdef Q_OS_WIN + QSKIP("This test opens a crash dialog on Windows", SkipSingle); +#endif + process = new QProcess; + process->start("testProcessCrash/testProcessCrash"); + QVERIFY(process->waitForStarted(5000)); + + qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError"); + qRegisterMetaType<QProcess::ProcessError>("QProcess::ExitStatus"); + + QSignalSpy spy(process, SIGNAL(error(QProcess::ProcessError))); + QSignalSpy spy2(process, SIGNAL(finished(int, QProcess::ExitStatus))); + + QObject::connect(process, SIGNAL(finished(int)), this, SLOT(exitLoopSlot())); + + QTestEventLoop::instance().enterLoop(5); + if (QTestEventLoop::instance().timeout()) + QFAIL("Failed to detect crash : operation timed out"); + + QCOMPARE(spy.count(), 1); + QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed); + + QCOMPARE(spy2.count(), 1); + QCOMPARE(*static_cast<const QProcess::ExitStatus *>(spy2.at(0).at(1).constData()), QProcess::CrashExit); + + QCOMPARE(process->exitStatus(), QProcess::CrashExit); + + delete process; + process = 0; +} + +//----------------------------------------------------------------------------- +void tst_QProcess::echoTest_data() +{ + QTest::addColumn<QByteArray>("input"); + + QTest::newRow("1") << QByteArray("H"); + QTest::newRow("2") << QByteArray("He"); + QTest::newRow("3") << QByteArray("Hel"); + QTest::newRow("4") << QByteArray("Hell"); + QTest::newRow("5") << QByteArray("Hello"); + QTest::newRow("100 bytes") << QByteArray(100, '@'); + QTest::newRow("1000 bytes") << QByteArray(1000, '@'); + QTest::newRow("10000 bytes") << QByteArray(10000, '@'); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::echoTest() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QFETCH(QByteArray, input); + + process = new QProcess; + connect(process, SIGNAL(readyRead()), this, SLOT(exitLoopSlot())); + +#ifdef Q_OS_MAC + process->start("testProcessEcho/testProcessEcho.app"); +#else + process->start("testProcessEcho/testProcessEcho"); +#endif + QVERIFY(process->waitForStarted(5000)); + + process->write(input); + + QTime stopWatch; + stopWatch.start(); + do { + QVERIFY(process->isOpen()); + QTestEventLoop::instance().enterLoop(2); + } while (stopWatch.elapsed() < 60000 && process->bytesAvailable() < input.size()); + if (stopWatch.elapsed() >= 60000) + QFAIL("Timed out"); + + QByteArray message = process->readAll(); + QCOMPARE(message.size(), input.size()); + + char *c1 = message.data(); + char *c2 = input.data(); + while (*c1 && *c2) { + if (*c1 != *c2) + QCOMPARE(*c1, *c2); + ++c1; + ++c2; + } + QCOMPARE(*c1, *c2); + + process->write("", 1); + + QVERIFY(process->waitForFinished(5000)); + + + delete process; + process = 0; +} + +//----------------------------------------------------------------------------- +void tst_QProcess::exitLoopSlot() +{ + QTestEventLoop::instance().exitLoop(); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::echoTest2() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + process = new QProcess; + connect(process, SIGNAL(readyRead()), this, SLOT(exitLoopSlot())); + +#ifdef Q_OS_MAC + process->start("testProcessEcho2/testProcessEcho2.app"); +#else + process->start("testProcessEcho2/testProcessEcho2"); +#endif + QVERIFY(process->waitForStarted(5000)); + QVERIFY(!process->waitForReadyRead(250)); + QCOMPARE(process->error(), QProcess::Timedout); + + process->write("Hello"); + QSignalSpy spy1(process, SIGNAL(readyReadStandardOutput())); + QSignalSpy spy2(process, SIGNAL(readyReadStandardError())); + + QTime stopWatch; + stopWatch.start(); + forever { + QTestEventLoop::instance().enterLoop(1); + if (stopWatch.elapsed() >= 30000) + QFAIL("Timed out"); + process->setReadChannel(QProcess::StandardOutput); + qint64 baso = process->bytesAvailable(); + + process->setReadChannel(QProcess::StandardError); + qint64 base = process->bytesAvailable(); + if (baso == 5 && base == 5) + break; + } + + QVERIFY(spy1.count() > 0); + QVERIFY(spy2.count() > 0); + + QCOMPARE(process->readAllStandardOutput(), QByteArray("Hello")); + QCOMPARE(process->readAllStandardError(), QByteArray("Hello")); + + process->write("", 1); + QVERIFY(process->waitForFinished(5000)); + + delete process; + process = 0; +} + +//----------------------------------------------------------------------------- +void tst_QProcess::echoTest_performance() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QProcess process; +#ifdef Q_OS_MAC + process.start("testProcessLoopback/testProcessLoopback.app"); +#else + process.start("testProcessLoopback/testProcessLoopback"); +#endif + + QByteArray array; + array.resize(1024 * 1024); + for (int j = 0; j < array.size(); ++j) + array[j] = 'a' + (j % 20); + + QVERIFY(process.waitForStarted()); + + QTime stopWatch; + stopWatch.start(); + + qint64 totalBytes = 0; + QByteArray dump; + QSignalSpy readyReadSpy(&process, SIGNAL(readyRead())); + while (stopWatch.elapsed() < 2000) { + process.write(array); + while (process.bytesToWrite() > 0) { + int readCount = readyReadSpy.count(); + QVERIFY(process.waitForBytesWritten(5000)); + if (readyReadSpy.count() == readCount) + QVERIFY(process.waitForReadyRead(5000)); + } + + while (process.bytesAvailable() < array.size()) + QVERIFY2(process.waitForReadyRead(5000), qPrintable(process.errorString())); + dump = process.readAll(); + totalBytes += dump.size(); + } + + qDebug() << "Elapsed time:" << stopWatch.elapsed() << "ms;" + << "transfer rate:" << totalBytes / (1048.576) / stopWatch.elapsed() + << "MB/s"; + + for (int j = 0; j < array.size(); ++j) + QCOMPARE(char(dump.at(j)), char('a' + (j % 20))); + + process.closeWriteChannel(); + QVERIFY(process.waitForFinished()); +} + +#if defined Q_OS_WIN +//----------------------------------------------------------------------------- +void tst_QProcess::echoTestGui() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QProcess process; + + process.start("testProcessEchoGui/testProcessEchoGui"); + + + process.write("Hello"); + process.write("q"); + + QVERIFY(process.waitForFinished(50000)); + + QCOMPARE(process.readAllStandardOutput(), QByteArray("Hello")); + QCOMPARE(process.readAllStandardError(), QByteArray("Hello")); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::batFiles_data() +{ + QTest::addColumn<QString>("batFile"); + QTest::addColumn<QByteArray>("output"); + + QTest::newRow("simple") << QString::fromLatin1("testBatFiles/simple.bat") << QByteArray("Hello"); + QTest::newRow("with space") << QString::fromLatin1("testBatFiles/with space.bat") << QByteArray("Hello"); +} + +void tst_QProcess::batFiles() +{ +#if defined(Q_OS_WINCE) + QSKIP("Batch files are not supported on Windows CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Batch files are not supported on Symbian", SkipAll); +#endif + QFETCH(QString, batFile); + QFETCH(QByteArray, output); + + QProcess proc; + + proc.start(batFile, QStringList()); + + QVERIFY(proc.waitForFinished(5000)); + + QVERIFY(proc.bytesAvailable() > 0); + + QVERIFY(proc.readAll().startsWith(output)); +} + +#endif + +//----------------------------------------------------------------------------- +void tst_QProcess::exitStatus_data() +{ + QTest::addColumn<QStringList>("processList"); + QTest::addColumn<QList<QProcess::ExitStatus> >("exitStatus"); + + QTest::newRow("normal") << (QStringList() << "testProcessNormal/testProcessNormal") + << (QList<QProcess::ExitStatus>() << QProcess::NormalExit); + QTest::newRow("crash") << (QStringList() << "testProcessCrash/testProcessCrash") + << (QList<QProcess::ExitStatus>() << QProcess::CrashExit); + + QTest::newRow("normal-crash") << (QStringList() + << "testProcessNormal/testProcessNormal" + << "testProcessCrash/testProcessCrash") + << (QList<QProcess::ExitStatus>() + << QProcess::NormalExit + << QProcess::CrashExit); + QTest::newRow("crash-normal") << (QStringList() + << "testProcessCrash/testProcessCrash" + << "testProcessNormal/testProcessNormal") + << (QList<QProcess::ExitStatus>() + << QProcess::CrashExit + << QProcess::NormalExit); +} + +void tst_QProcess::exitStatus() +{ + process = new QProcess; + QFETCH(QStringList, processList); + QFETCH(QList<QProcess::ExitStatus>, exitStatus); + +#ifdef Q_OS_WIN + if (exitStatus.contains(QProcess::CrashExit)) + QSKIP("This test opens a crash dialog on Windows", SkipSingle); +#endif + + Q_ASSERT(processList.count() == exitStatus.count()); + for (int i = 0; i < processList.count(); ++i) { + process->start(processList.at(i)); + QVERIFY(process->waitForStarted(5000)); + QVERIFY(process->waitForFinished(5000)); + + QCOMPARE(process->exitStatus(), exitStatus.at(i)); + } + + process->deleteLater(); + process = 0; +} +//----------------------------------------------------------------------------- +void tst_QProcess::loopBackTest() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + process = new QProcess; +#ifdef Q_OS_MAC + process->start("testProcessEcho/testProcessEcho.app"); +#else + process->start("testProcessEcho/testProcessEcho"); +#endif + QVERIFY(process->waitForStarted(5000)); + + for (int i = 0; i < 100; ++i) { + process->write("Hello"); + do { + QVERIFY(process->waitForReadyRead(5000)); + } while (process->bytesAvailable() < 5); + QCOMPARE(process->readAll(), QByteArray("Hello")); + } + + process->write("", 1); + QVERIFY(process->waitForFinished(5000)); + + delete process; + process = 0; +} + +//----------------------------------------------------------------------------- +void tst_QProcess::readTimeoutAndThenCrash() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + process = new QProcess; +#ifdef Q_OS_MAC + process->start("testProcessEcho/testProcessEcho.app"); +#else + process->start("testProcessEcho/testProcessEcho"); +#endif + if (process->state() != QProcess::Starting) + QCOMPARE(process->state(), QProcess::Running); + + QVERIFY(process->waitForStarted(5000)); + QCOMPARE(process->state(), QProcess::Running); + + QVERIFY(!process->waitForReadyRead(5000)); + QCOMPARE(process->error(), QProcess::Timedout); + + qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError"); + QSignalSpy spy(process, SIGNAL(error(QProcess::ProcessError))); + + process->kill(); + + QVERIFY(process->waitForFinished(5000)); + QCOMPARE(process->state(), QProcess::NotRunning); + + QCOMPARE(spy.count(), 1); + QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed); + + delete process; + process = 0; +} + +void tst_QProcess::waitForFinished() +{ + QProcess process; + +#ifdef Q_OS_MAC + process.start("testProcessOutput/testProcessOutput.app"); +#else + process.start("testProcessOutput/testProcessOutput"); +#endif + +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) + QVERIFY(process.waitForFinished(5000)); +#else + QVERIFY(process.waitForFinished(30000)); +#endif + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + +#if defined(Q_OS_SYMBIAN) + // Symbian test outputs to a file, so check that + FILE* file = fopen("c:\\logs\\qprocess_output_test.txt","r"); + int retval = 0; + int count = 0; + while((int)(retval = fgetc(file) )!= EOF) + if (retval == '\n') + count++; + fclose(file); + QCOMPARE(count, 200); +#else +# if defined (Q_OS_WINCE) + QEXPECT_FAIL("", "Reading and writing to a process is not supported on Qt/CE", Continue); +# endif + QString output = process.readAll(); + QCOMPARE(output.count("\n"), 10*1024); +#endif + + process.start("blurdybloop"); + QVERIFY(!process.waitForFinished()); + QCOMPARE(process.error(), QProcess::FailedToStart); +} + + +void tst_QProcess::deadWhileReading() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QProcess process; + +#ifdef Q_OS_MAC + process.start("testProcessDeadWhileReading/testProcessDeadWhileReading.app"); +#else + process.start("testProcessDeadWhileReading/testProcessDeadWhileReading"); +#endif + + QString output; + + QVERIFY(process.waitForStarted(5000)); + while (process.waitForReadyRead(5000)) + output += process.readAll(); + + QCOMPARE(output.count("\n"), 10*1024); + process.waitForFinished(); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::restartProcessDeadlock() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + // The purpose of this test is to detect whether restarting a + // process in the finished() connected slot causes a deadlock + // because of the way QProcessManager uses its locks. + QProcess proc; + process = &proc; + connect(process, SIGNAL(finished(int)), this, SLOT(restartProcess())); + +#ifdef Q_OS_MAC + process->start("testProcessEcho/testProcessEcho.app"); +#else + process->start("testProcessEcho/testProcessEcho"); +#endif + + QCOMPARE(process->write("", 1), qlonglong(1)); + QVERIFY(process->waitForFinished(5000)); + + process->disconnect(SIGNAL(finished(int))); + + QCOMPARE(process->write("", 1), qlonglong(1)); + QVERIFY(process->waitForFinished(5000)); +} + +void tst_QProcess::restartProcess() +{ +#ifdef Q_OS_MAC + process->start("testProcessEcho/testProcessEcho.app"); +#else + process->start("testProcessEcho/testProcessEcho"); +#endif +} + +//----------------------------------------------------------------------------- +void tst_QProcess::closeWriteChannel() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QProcess more; + more.start("testProcessEOF/testProcessEOF"); + + QVERIFY(more.waitForStarted(5000)); + QVERIFY(!more.waitForReadyRead(250)); + QCOMPARE(more.error(), QProcess::Timedout); + + QVERIFY(more.write("Data to read") != -1); + + QVERIFY(!more.waitForReadyRead(250)); + QCOMPARE(more.error(), QProcess::Timedout); + + more.closeWriteChannel(); + + QVERIFY(more.waitForReadyRead(5000)); + QVERIFY(more.readAll().startsWith("Data to read")); + + if (more.state() == QProcess::Running) + more.write("q"); + QVERIFY(more.waitForFinished(5000)); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::closeReadChannel() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + for (int i = 0; i < 10; ++i) { + QProcess::ProcessChannel channel1 = QProcess::StandardOutput; + QProcess::ProcessChannel channel2 = QProcess::StandardError; + + QProcess proc; +#ifdef Q_OS_MAC + proc.start("testProcessEcho2/testProcessEcho2.app"); +#else + proc.start("testProcessEcho2/testProcessEcho2"); +#endif + QVERIFY(proc.waitForStarted(5000)); + proc.closeReadChannel(i&1 ? channel2 : channel1); + proc.setReadChannel(i&1 ? channel2 : channel1); + proc.write("Data"); + + QVERIFY(!proc.waitForReadyRead(5000)); + QVERIFY(proc.readAll().isEmpty()); + + proc.setReadChannel(i&1 ? channel1 : channel2); + + while (proc.bytesAvailable() < 4 && proc.waitForReadyRead(5000)) + { } + + QCOMPARE(proc.readAll(), QByteArray("Data")); + + proc.write("", 1); + QVERIFY(proc.waitForFinished(5000)); + } +} + +//----------------------------------------------------------------------------- +void tst_QProcess::openModes() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QProcess proc; + QVERIFY(!proc.isOpen()); + QVERIFY(proc.openMode() == QProcess::NotOpen); +#ifdef Q_OS_MAC + proc.start("testProcessEcho3/testProcessEcho3.app"); +#else + proc.start("testProcessEcho3/testProcessEcho3"); +#endif + QVERIFY(proc.waitForStarted(5000)); + QVERIFY(proc.isOpen()); + QVERIFY(proc.openMode() == QProcess::ReadWrite); + QVERIFY(proc.isReadable()); + QVERIFY(proc.isWritable()); + + proc.write("Data"); + + proc.closeWriteChannel(); + + QVERIFY(proc.isWritable()); + QVERIFY(proc.openMode() == QProcess::ReadWrite); + + while (proc.bytesAvailable() < 4 && proc.waitForReadyRead(5000)) + { } + + QCOMPARE(proc.readAll().constData(), QByteArray("Data").constData()); + + proc.closeReadChannel(QProcess::StandardOutput); + + QVERIFY(proc.openMode() == QProcess::ReadWrite); + QVERIFY(proc.isReadable()); + + proc.closeReadChannel(QProcess::StandardError); + + QVERIFY(proc.openMode() == QProcess::ReadWrite); + QVERIFY(proc.isReadable()); + + proc.close(); + QVERIFY(!proc.isOpen()); + QVERIFY(!proc.isReadable()); + QVERIFY(!proc.isWritable()); + QCOMPARE(proc.state(), QProcess::NotRunning); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::emitReadyReadOnlyWhenNewDataArrives() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QProcess proc; + connect(&proc, SIGNAL(readyRead()), this, SLOT(exitLoopSlot())); + QSignalSpy spy(&proc, SIGNAL(readyRead())); + +#ifdef Q_OS_MAC + proc.start("testProcessEcho/testProcessEcho.app"); +#else + proc.start("testProcessEcho/testProcessEcho"); +#endif + + QCOMPARE(spy.count(), 0); + + proc.write("A"); + + QTestEventLoop::instance().enterLoop(5); + if (QTestEventLoop::instance().timeout()) + QFAIL("Operation timed out"); + + QCOMPARE(spy.count(), 1); + + QTestEventLoop::instance().enterLoop(1); + QVERIFY(QTestEventLoop::instance().timeout()); + QVERIFY(!proc.waitForReadyRead(250)); + + QObject::disconnect(&proc, SIGNAL(readyRead()), 0, 0); + proc.write("B"); + QVERIFY(proc.waitForReadyRead(5000)); + + proc.write("", 1); + QVERIFY(proc.waitForFinished(5000)); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::hardExit() +{ +#if defined(Q_OS_SYMBIAN) + QSKIP("Killing started processes is not supported on Qt/Symbian due platform security", SkipAll); +#endif + QProcess proc; + +#if defined(Q_OS_MAC) + proc.start("testProcessEcho/testProcessEcho.app"); +#elif defined(Q_OS_WINCE) + proc.start("testSoftExit/testSoftExit"); +#else + proc.start("testProcessEcho/testProcessEcho"); +#endif + +#ifndef Q_OS_WINCE + QVERIFY(proc.waitForStarted(5000)); +#else + QVERIFY(proc.waitForStarted(10000)); +#endif + + proc.kill(); + + QVERIFY(proc.waitForFinished(5000)); + QCOMPARE(int(proc.state()), int(QProcess::NotRunning)); + QCOMPARE(int(proc.error()), int(QProcess::Crashed)); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::softExit() +{ +#if defined(Q_OS_SYMBIAN) + QSKIP("Terminating started processes is not supported on Qt/Symbian due platform security", SkipAll); +#endif + QProcess proc; + + proc.start("testSoftExit/testSoftExit"); + + QVERIFY(proc.waitForStarted(10000)); +#if !defined(Q_OS_WINCE) + QVERIFY(proc.waitForReadyRead(10000)); +#endif + + proc.terminate(); + + QVERIFY(proc.waitForFinished(10000)); + QCOMPARE(int(proc.state()), int(QProcess::NotRunning)); + QCOMPARE(int(proc.error()), int(QProcess::UnknownError)); +} + +class SoftExitProcess : public QProcess +{ + Q_OBJECT +public: + bool waitedForFinished; + + SoftExitProcess(int n) : waitedForFinished(false), n(n), killing(false) + { + connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(finishedSlot(int, QProcess::ExitStatus))); + + switch (n) { + case 0: + setReadChannelMode(QProcess::MergedChannels); + connect(this, SIGNAL(readyRead()), this, SLOT(terminateSlot())); + break; + case 1: + connect(this, SIGNAL(readyReadStandardOutput()), + this, SLOT(terminateSlot())); + break; + case 2: + connect(this, SIGNAL(readyReadStandardError()), + this, SLOT(terminateSlot())); + break; + case 3: + connect(this, SIGNAL(started()), + this, SLOT(terminateSlot())); + break; + case 4: + default: + connect(this, SIGNAL(stateChanged(QProcess::ProcessState)), + this, SLOT(terminateSlot())); + break; + } + } + +public slots: + void terminateSlot() + { + if (killing || (n == 4 && state() != Running)) { + // Don't try to kill the process before it is running - that can + // be hazardous, as the actual child process might not be running + // yet. Also, don't kill it "recursively". + return; + } + killing = true; + readAll(); + terminate(); + if ((waitedForFinished = waitForFinished(5000)) == false) { + kill(); + if (state() != NotRunning) + waitedForFinished = waitForFinished(5000); + } + } + + void finishedSlot(int, QProcess::ExitStatus) + { + waitedForFinished = true; + } + +private: + int n; + bool killing; +}; + +//----------------------------------------------------------------------------- +void tst_QProcess::softExitInSlots_data() +{ + QTest::addColumn<QString>("appName"); + +#ifdef Q_OS_MAC + QTest::newRow("gui app") << "testGuiProcess/testGuiProcess.app"; +#else + QTest::newRow("gui app") << "testGuiProcess/testGuiProcess"; +#endif +#ifdef Q_OS_MAC + QTest::newRow("console app") << "testProcessEcho2/testProcessEcho2.app"; +#else + QTest::newRow("console app") << "testProcessEcho2/testProcessEcho2"; +#endif +} + +//----------------------------------------------------------------------------- +void tst_QProcess::softExitInSlots() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QFETCH(QString, appName); + + for (int i = 0; i < 5; ++i) { + SoftExitProcess proc(i); + proc.start(appName); + proc.write("OLEBOLE", 8); // include the \0 + QTestEventLoop::instance().enterLoop(1); + QCOMPARE(proc.state(), QProcess::NotRunning); + QVERIFY(proc.waitedForFinished); + } +} + +//----------------------------------------------------------------------------- +void tst_QProcess::mergedChannels() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QProcess process; + process.setReadChannelMode(QProcess::MergedChannels); + QCOMPARE(process.readChannelMode(), QProcess::MergedChannels); + +#ifdef Q_OS_MAC + process.start("testProcessEcho2/testProcessEcho2.app"); +#else + process.start("testProcessEcho2/testProcessEcho2"); +#endif + + QVERIFY(process.waitForStarted(5000)); + + for (int i = 0; i < 100; ++i) { + QCOMPARE(process.write("abc"), qlonglong(3)); + while (process.bytesAvailable() < 6) + QVERIFY(process.waitForReadyRead(5000)); + QCOMPARE(process.readAll(), QByteArray("aabbcc")); + } + + process.closeWriteChannel(); + QVERIFY(process.waitForFinished(5000)); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::forwardedChannels() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QProcess process; + process.setReadChannelMode(QProcess::ForwardedChannels); + QCOMPARE(process.readChannelMode(), QProcess::ForwardedChannels); + +#ifdef Q_OS_MAC + process.start("testProcessEcho2/testProcessEcho2.app"); +#else + process.start("testProcessEcho2/testProcessEcho2"); +#endif + + QVERIFY(process.waitForStarted(5000)); + QCOMPARE(process.write("forwarded\n"), qlonglong(10)); + QVERIFY(!process.waitForReadyRead(250)); + QCOMPARE(process.bytesAvailable(), qlonglong(0)); + + process.closeWriteChannel(); + QVERIFY(process.waitForFinished(5000)); +} + + +//----------------------------------------------------------------------------- +void tst_QProcess::atEnd() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QProcess process; + +#ifdef Q_OS_MAC + process.start("testProcessEcho/testProcessEcho.app"); +#else + process.start("testProcessEcho/testProcessEcho"); +#endif + process.write("abcdefgh\n"); + + while (process.bytesAvailable() < 8) + QVERIFY(process.waitForReadyRead(5000)); + + QTextStream stream(&process); + QVERIFY(!stream.atEnd()); + QString tmp = stream.readLine(); + QVERIFY(stream.atEnd()); + QCOMPARE(tmp, QString::fromLatin1("abcdefgh")); + + process.write("", 1); + QVERIFY(process.waitForFinished(5000)); +} + +class TestThread : public QThread +{ + Q_OBJECT +public: + inline int code() + { + return exitCode; + } + +#if defined(Q_OS_SYMBIAN) + int serial; +#endif + +protected: + inline void run() + { + exitCode = 90210; + + QProcess process; + connect(&process, SIGNAL(finished(int)), this, SLOT(catchExitCode(int)), + Qt::DirectConnection); + +#ifdef Q_OS_MAC + process.start("testProcessEcho/testProcessEcho.app"); +#elif defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) + // WINSCW builds in Symbian do not allow multiple processes to load Qt libraries, + // so use just a simple process instead of testDetached. + process.start("testProcessNormal"); +#elif defined(Q_OS_SYMBIAN) + // testDetached used because it does something, but doesn't take too long. + QFile infoFile(QString("c:\\logs\\detinfo%1").arg(serial)); + QStringList args; + args << infoFile.fileName(); + process.start("testDetached", args); +#else + process.start("testProcessEcho/testProcessEcho"); +#endif + +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) + QCOMPARE(process.write("abc\0", 4), qint64(4)); +#endif + exitCode = exec(); + } + +protected slots: + inline void catchExitCode(int exitCode) + { + this->exitCode = exitCode; + exit(exitCode); + } + +private: + int exitCode; +}; + +//----------------------------------------------------------------------------- +void tst_QProcess::processInAThread() +{ + for (int i = 0; i < 3; ++i) { + TestThread thread; +#if defined(Q_OS_SYMBIAN) + thread.setStackSize(0x14000); +#endif + thread.start(); + QVERIFY(thread.wait(10000)); + QCOMPARE(thread.code(), 0); + } +} + +//----------------------------------------------------------------------------- +void tst_QProcess::processesInMultipleThreads() +{ +#if defined(Q_OS_SYMBIAN) + int serialCounter = 0; +#endif + + for (int i = 0; i < 10; ++i) { + TestThread thread1; + TestThread thread2; + TestThread thread3; + +#if defined(Q_OS_SYMBIAN) + thread1.serial = serialCounter++; + thread2.serial = serialCounter++; + thread3.serial = serialCounter++; + + thread1.setStackSize(0x14000); + thread2.setStackSize(0x14000); + thread3.setStackSize(0x14000); +#endif + thread1.start(); + thread2.start(); + thread3.start(); + + QVERIFY(thread2.wait(10000)); + QVERIFY(thread3.wait(10000)); + QVERIFY(thread1.wait(10000)); + + QCOMPARE(thread1.code(), 0); + QCOMPARE(thread2.code(), 0); + QCOMPARE(thread3.code(), 0); + } +} + +//----------------------------------------------------------------------------- +void tst_QProcess::waitForFinishedWithTimeout() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif + + process = new QProcess(this); + +#ifdef Q_OS_MAC + process->start("testProcessEcho/testProcessEcho.app"); +#elif defined(Q_OS_SYMBIAN) + process->start("testProcessOutput"); +#else + process->start("testProcessEcho/testProcessEcho"); +#endif + +#if defined(Q_OS_SYMBIAN) + QVERIFY(process->waitForStarted(50)); + QVERIFY(!process->waitForFinished(1)); +#else + QVERIFY(process->waitForStarted(5000)); + QVERIFY(!process->waitForFinished(1)); + + process->write("", 1); +#endif + + QVERIFY(process->waitForFinished()); + + delete process; + process = 0; +} + +//----------------------------------------------------------------------------- +void tst_QProcess::waitForReadyReadInAReadyReadSlot() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + process = new QProcess(this); + connect(process, SIGNAL(readyRead()), this, SLOT(waitForReadyReadInAReadyReadSlotSlot())); + connect(process, SIGNAL(finished(int)), this, SLOT(exitLoopSlot())); + bytesAvailable = 0; + +#ifdef Q_OS_MAC + process->start("testProcessEcho/testProcessEcho.app"); +#else + process->start("testProcessEcho/testProcessEcho"); +#endif + QVERIFY(process->waitForStarted(5000)); + + QSignalSpy spy(process, SIGNAL(readyRead())); + process->write("foo"); + QTestEventLoop::instance().enterLoop(30); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(spy.count(), 1); + + process->disconnect(); + QVERIFY(process->waitForFinished(5000)); + QVERIFY(process->bytesAvailable() > bytesAvailable); + delete process; + process = 0; +} + +//----------------------------------------------------------------------------- +void tst_QProcess::waitForReadyReadInAReadyReadSlotSlot() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + bytesAvailable = process->bytesAvailable(); + process->write("bar", 4); + QVERIFY(process->waitForReadyRead(5000)); + QTestEventLoop::instance().exitLoop(); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::waitForBytesWrittenInABytesWrittenSlot() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + process = new QProcess(this); + connect(process, SIGNAL(bytesWritten(qint64)), this, SLOT(waitForBytesWrittenInABytesWrittenSlotSlot())); + bytesAvailable = 0; + +#ifdef Q_OS_MAC + process->start("testProcessEcho/testProcessEcho.app"); +#else + process->start("testProcessEcho/testProcessEcho"); +#endif + QVERIFY(process->waitForStarted(5000)); + + qRegisterMetaType<qint64>("qint64"); + QSignalSpy spy(process, SIGNAL(bytesWritten(qint64))); + process->write("f"); + QTestEventLoop::instance().enterLoop(30); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(spy.count(), 1); + process->write("", 1); + process->disconnect(); + QVERIFY(process->waitForFinished()); + delete process; + process = 0; +} + +//----------------------------------------------------------------------------- +void tst_QProcess::waitForBytesWrittenInABytesWrittenSlotSlot() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + process->write("b"); + QVERIFY(process->waitForBytesWritten(5000)); + QTestEventLoop::instance().exitLoop(); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::spaceArgsTest_data() +{ + QTest::addColumn<QStringList>("args"); + QTest::addColumn<QString>("stringArgs"); + + // arg1 | arg2 + QTest::newRow("arg1 arg2") << (QStringList() << QString::fromLatin1("arg1") << QString::fromLatin1("arg2")) + << QString::fromLatin1("arg1 arg2"); + // "arg1" | ar "g2 + QTest::newRow("\"\"\"\"arg1\"\"\"\" \"ar \"\"\"g2\"") << (QStringList() << QString::fromLatin1("\"arg1\"") << QString::fromLatin1("ar \"g2")) + << QString::fromLatin1("\"\"\"\"arg1\"\"\"\" \"ar \"\"\"g2\""); + // ar g1 | a rg 2 + QTest::newRow("\"ar g1\" \"a rg 2\"") << (QStringList() << QString::fromLatin1("ar g1") << QString::fromLatin1("a rg 2")) + << QString::fromLatin1("\"ar g1\" \"a rg 2\""); + // -lar g1 | -l"ar g2" + QTest::newRow("\"-lar g1\" \"-l\"\"\"ar g2\"\"\"\"") << (QStringList() << QString::fromLatin1("-lar g1") << QString::fromLatin1("-l\"ar g2\"")) + << QString::fromLatin1("\"-lar g1\" \"-l\"\"\"ar g2\"\"\"\""); + // ar"g1 + QTest::newRow("ar\"\"\"\"g1") << (QStringList() << QString::fromLatin1("ar\"g1")) + << QString::fromLatin1("ar\"\"\"\"g1"); + // ar/g1 + QTest::newRow("ar\\g1") << (QStringList() << QString::fromLatin1("ar\\g1")) + << QString::fromLatin1("ar\\g1"); + // ar\g"1 + QTest::newRow("ar\\g\"\"\"\"1") << (QStringList() << QString::fromLatin1("ar\\g\"1")) + << QString::fromLatin1("ar\\g\"\"\"\"1"); + // arg\"1 + QTest::newRow("arg\\\"\"\"1") << (QStringList() << QString::fromLatin1("arg\\\"1")) + << QString::fromLatin1("arg\\\"\"\"1"); + // """" + QTest::newRow("\"\"\"\"\"\"\"\"\"\"\"\"") << (QStringList() << QString::fromLatin1("\"\"\"\"")) + << QString::fromLatin1("\"\"\"\"\"\"\"\"\"\"\"\""); + // """" | "" "" + QTest::newRow("\"\"\"\"\"\"\"\"\"\"\"\" \"\"\"\"\"\"\" \"\"\"\"\"\"\"") << (QStringList() << QString::fromLatin1("\"\"\"\"") << QString::fromLatin1("\"\" \"\"")) + << QString::fromLatin1("\"\"\"\"\"\"\"\"\"\"\"\" \"\"\"\"\"\"\" \"\"\"\"\"\"\""); + // "" "" + QTest::newRow("\"\"\"\"\"\"\" \"\" \"\"\"\"\"\"\" (bogus double quotes)") << (QStringList() << QString::fromLatin1("\"\" \"\"")) + << QString::fromLatin1("\"\"\"\"\"\"\" \"\" \"\"\"\"\"\"\""); + // "" "" + QTest::newRow(" \"\"\"\"\"\"\" \"\" \"\"\"\"\"\"\" (bogus double quotes)") << (QStringList() << QString::fromLatin1("\"\" \"\"")) + << QString::fromLatin1(" \"\"\"\"\"\"\" \"\" \"\"\"\"\"\"\" "); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::spaceArgsTest() +{ + QFETCH(QStringList, args); + QFETCH(QString, stringArgs); + + QStringList programs; + programs << QString::fromLatin1("testProcessSpacesArgs/nospace") +#if defined(Q_OS_SYMBIAN) + ; // Symbian toolchain doesn't like exes with spaces in the name +#else + << QString::fromLatin1("testProcessSpacesArgs/one space") + << QString::fromLatin1("testProcessSpacesArgs/two space s"); +#endif + + process = new QProcess(this); + + for (int i = 0; i < programs.size(); ++i) { + QString program = programs.at(i); + process->start(program, args); + +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) + QVERIFY(process->waitForStarted(5000)); + QVERIFY(process->waitForFinished(5000)); +#else + QVERIFY(process->waitForStarted(10000)); + QVERIFY(process->waitForFinished(10000)); +#endif + +#if defined(Q_OS_SYMBIAN) + // Symbian test outputs to a file, so check that + FILE* file = fopen("c:\\logs\\qprocess_args_test.txt","r"); + char buf[256]; + fgets(buf, 256, file); + fclose(file); + QStringList actual = QString::fromLatin1(buf).split("|"); +#elif !defined(Q_OS_WINCE) + QStringList actual = QString::fromLatin1(process->readAll()).split("|"); +#endif +#if !defined(Q_OS_WINCE) + QVERIFY(!actual.isEmpty()); + // not interested in the program name, it might be different. + actual.removeFirst(); + + QCOMPARE(actual, args); +#endif + + if (program.contains(" ")) + program = "\"" + program + "\""; + + if (!stringArgs.isEmpty()) + program += QString::fromLatin1(" ") + stringArgs; + + process->start(program); + + QVERIFY(process->waitForStarted(5000)); + QVERIFY(process->waitForFinished(5000)); + +#if defined(Q_OS_SYMBIAN) + // Symbian test outputs to a file, so check that + file = fopen("c:\\logs\\qprocess_args_test.txt","r"); + fgets(buf, 256, file); + fclose(file); + actual = QString::fromLatin1(buf).split("|"); +#elif !defined(Q_OS_WINCE) + actual = QString::fromLatin1(process->readAll()).split("|"); +#endif +#if !defined(Q_OS_WINCE) + QVERIFY(!actual.isEmpty()); + // not interested in the program name, it might be different. + actual.removeFirst(); + + QCOMPARE(actual, args); +#endif + } + + delete process; + process = 0; +} + +//----------------------------------------------------------------------------- +void tst_QProcess::exitCodeTest() +{ +#if defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) + // WINSCW builds in Symbian panic somewhere deep inside Symbian codes + // when eventdispather is deleted if too many test iterations are used. + // Reason for this is unclear. + // TODO: Remove special case when eventdispatcher is fixed. + for (int i = 0; i < 25; ++i) { +#else + for (int i = 0; i < 255; ++i) { +#endif + QProcess process; + process.start("testExitCodes/testExitCodes " + QString::number(i)); + QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitCode(), i); + QCOMPARE(process.error(), QProcess::UnknownError); + } +} + +//----------------------------------------------------------------------------- +void tst_QProcess::failToStart() +{ + qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError"); + qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus"); + qRegisterMetaType<QProcess::ProcessState>("QProcess::ProcessState"); + + QProcess process; + QSignalSpy stateSpy(&process, SIGNAL(stateChanged(QProcess::ProcessState))); + QSignalSpy errorSpy(&process, SIGNAL(error(QProcess::ProcessError))); + QSignalSpy finishedSpy(&process, SIGNAL(finished(int))); + QSignalSpy finishedSpy2(&process, SIGNAL(finished(int, QProcess::ExitStatus))); + +// Mac OS X and HP-UX have a really low defualt process limit (~100), so spawning +// to many processes here will cause test failures later on. +#if defined Q_OS_HPUX + const int attempts = 15; +#elif defined Q_OS_MAC + const int attempts = 15; +#else + const int attempts = 50; +#endif + + for (int j = 0; j < 8; ++j) { + for (int i = 0; i < attempts; ++i) { + QCOMPARE(errorSpy.count(), j * attempts + i); + process.start("/blurp"); + + switch (j) { + case 0: + case 1: + QVERIFY(!process.waitForStarted()); + break; + case 2: + case 3: + QVERIFY(!process.waitForFinished()); + break; + case 4: + case 5: + QVERIFY(!process.waitForReadyRead()); + break; + case 6: + case 7: + default: + QVERIFY(!process.waitForBytesWritten()); + break; + } + + QCOMPARE(process.error(), QProcess::FailedToStart); + QCOMPARE(errorSpy.count(), j * attempts + i + 1); + QCOMPARE(finishedSpy.count(), 0); + QCOMPARE(finishedSpy2.count(), 0); + + int it = j * attempts + i + 1; + + QCOMPARE(stateSpy.count(), it * 2); + QCOMPARE(qVariantValue<QProcess::ProcessState>(stateSpy.at(it * 2 - 2).at(0)), QProcess::Starting); + QCOMPARE(qVariantValue<QProcess::ProcessState>(stateSpy.at(it * 2 - 1).at(0)), QProcess::NotRunning); + } + } +} + +//----------------------------------------------------------------------------- +void tst_QProcess::failToStartWithWait() +{ + qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError"); + qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus"); + + QProcess process; + QEventLoop loop; + QSignalSpy errorSpy(&process, SIGNAL(error(QProcess::ProcessError))); + QSignalSpy finishedSpy(&process, SIGNAL(finished(int))); + QSignalSpy finishedSpy2(&process, SIGNAL(finished(int, QProcess::ExitStatus))); + + for (int i = 0; i < 50; ++i) { + process.start("/blurp", QStringList() << "-v" << "-debug"); + process.waitForStarted(); + + QCOMPARE(process.error(), QProcess::FailedToStart); + QCOMPARE(errorSpy.count(), i + 1); + QCOMPARE(finishedSpy.count(), 0); + QCOMPARE(finishedSpy2.count(), 0); + } +} + +//----------------------------------------------------------------------------- +void tst_QProcess::failToStartWithEventLoop() +{ + qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError"); + qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus"); + + QProcess process; + QEventLoop loop; + QSignalSpy errorSpy(&process, SIGNAL(error(QProcess::ProcessError))); + QSignalSpy finishedSpy(&process, SIGNAL(finished(int))); + QSignalSpy finishedSpy2(&process, SIGNAL(finished(int, QProcess::ExitStatus))); + + // The error signal may be emitted before start() returns + connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit()), Qt::QueuedConnection); + + + for (int i = 0; i < 50; ++i) { + process.start("/blurp", QStringList() << "-v" << "-debug"); + + loop.exec(); + + QCOMPARE(process.error(), QProcess::FailedToStart); + QCOMPARE(errorSpy.count(), i + 1); + QCOMPARE(finishedSpy.count(), 0); + QCOMPARE(finishedSpy2.count(), 0); + } +} + +//----------------------------------------------------------------------------- +void tst_QProcess::removeFileWhileProcessIsRunning() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QFile file("removeFile.txt"); + QVERIFY(file.open(QFile::WriteOnly)); + + QProcess process; +#ifdef Q_OS_MAC + process.start("testProcessEcho/testProcessEcho.app"); +#else + process.start("testProcessEcho/testProcessEcho"); +#endif + + QVERIFY(process.waitForStarted(5000)); + + QVERIFY(file.remove()); + + process.write("", 1); + QVERIFY(process.waitForFinished(5000)); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::systemEnvironment() +{ +#if defined (Q_OS_WINCE) || defined(Q_OS_SYMBIAN) + // there is no concept of system variables on Windows CE as there is no console + QVERIFY(QProcess::systemEnvironment().isEmpty()); +#else + QVERIFY(!QProcess::systemEnvironment().isEmpty()); +#endif +} + +//----------------------------------------------------------------------------- +void tst_QProcess::spaceInName() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + QProcess process; + process.start("test Space In Name/testSpaceInName", QStringList()); + QVERIFY(process.waitForStarted()); + process.write("", 1); + QVERIFY(process.waitForFinished()); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::lockupsInStartDetached() +{ +#if !defined(Q_OS_SYMBIAN) + // What exactly is this call supposed to achieve anyway? + QHostInfo::lookupHost(QString("something.invalid"), 0, 0); +#endif + QProcess::execute("yjhbrty"); + QProcess::startDetached("yjhbrty"); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::atEnd2() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QProcess process; + +#ifdef Q_OS_MAC + process.start("testProcessEcho/testProcessEcho.app"); +#else + process.start("testProcessEcho/testProcessEcho"); +#endif + process.write("Foo\nBar\nBaz\nBodukon\nHadukan\nTorwukan\nend\n"); + process.putChar('\0'); + QVERIFY(process.waitForFinished()); + QList<QByteArray> lines; + while (!process.atEnd()) { + lines << process.readLine(); + } + QCOMPARE(lines.size(), 7); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::waitForReadyReadForNonexistantProcess() +{ + // This comes from task 108968 + // Start a program that doesn't exist, process events and then try to waitForReadyRead + qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError"); + qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus"); + + QProcess process; + QSignalSpy errorSpy(&process, SIGNAL(error(QProcess::ProcessError))); + QSignalSpy finishedSpy1(&process, SIGNAL(finished(int))); + QSignalSpy finishedSpy2(&process, SIGNAL(finished(int, QProcess::ExitStatus))); + QVERIFY(!process.waitForReadyRead()); // used to crash + process.start("doesntexist"); + QVERIFY(!process.waitForReadyRead()); + QCOMPARE(errorSpy.count(), 1); + QCOMPARE(errorSpy.at(0).at(0).toInt(), 0); + QCOMPARE(finishedSpy1.count(), 0); + QCOMPARE(finishedSpy2.count(), 0); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::setStandardInputFile() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + static const char data[] = "A bunch\1of\2data\3\4\5\6\7..."; + QProcess process; + QFile file("data"); + + QVERIFY(file.open(QIODevice::WriteOnly)); + file.write(data, sizeof data); + file.close(); + + process.setStandardInputFile("data"); +#ifdef Q_OS_MAC + process.start("testProcessEcho/testProcessEcho.app"); +#else + process.start("testProcessEcho/testProcessEcho"); +#endif + + QPROCESS_VERIFY(process, waitForFinished()); + QByteArray all = process.readAll(); + QCOMPARE(all.size(), int(sizeof data) - 1); // testProcessEcho drops the ending \0 + QVERIFY(all == data); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::setStandardOutputFile_data() +{ + QTest::addColumn<int>("channelToTest"); + QTest::addColumn<int>("_channelMode"); + QTest::addColumn<bool>("append"); + + QTest::newRow("stdout-truncate") << int(QProcess::StandardOutput) + << int(QProcess::SeparateChannels) + << false; + QTest::newRow("stdout-append") << int(QProcess::StandardOutput) + << int(QProcess::SeparateChannels) + << true; + + QTest::newRow("stderr-truncate") << int(QProcess::StandardError) + << int(QProcess::SeparateChannels) + << false; + QTest::newRow("stderr-append") << int(QProcess::StandardError) + << int(QProcess::SeparateChannels) + << true; + + QTest::newRow("merged-truncate") << int(QProcess::StandardOutput) + << int(QProcess::MergedChannels) + << false; + QTest::newRow("merged-append") << int(QProcess::StandardOutput) + << int(QProcess::MergedChannels) + << true; +} + +void tst_QProcess::setStandardOutputFile() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + static const char data[] = "Original data. "; + static const char testdata[] = "Test data."; + + QFETCH(int, channelToTest); + QFETCH(int, _channelMode); + QFETCH(bool, append); + + QProcess::ProcessChannelMode channelMode = QProcess::ProcessChannelMode(_channelMode); + QIODevice::OpenMode mode = append ? QIODevice::Append : QIODevice::Truncate; + + // create the destination file with data + QFile file("data"); + QVERIFY(file.open(QIODevice::WriteOnly)); + file.write(data, sizeof data - 1); + file.close(); + + // run the process + QProcess process; + process.setReadChannelMode(channelMode); + if (channelToTest == QProcess::StandardOutput) + process.setStandardOutputFile("data", mode); + else + process.setStandardErrorFile("data", mode); + +#ifdef Q_OS_MAC + process.start("testProcessEcho2/testProcessEcho2.app"); +#else + process.start("testProcessEcho2/testProcessEcho2"); +#endif + process.write(testdata, sizeof testdata); + QPROCESS_VERIFY(process,waitForFinished()); + + // open the file again and verify the data + QVERIFY(file.open(QIODevice::ReadOnly)); + QByteArray all = file.readAll(); + file.close(); + + int expectedsize = sizeof testdata - 1; + if (mode == QIODevice::Append) { + QVERIFY(all.startsWith(data)); + expectedsize += sizeof data - 1; + } + if (channelMode == QProcess::MergedChannels) { + expectedsize += sizeof testdata - 1; + } else { + QVERIFY(all.endsWith(testdata)); + } + + QCOMPARE(all.size(), expectedsize); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::setStandardOutputProcess_data() +{ + QTest::addColumn<bool>("merged"); + QTest::newRow("separate") << false; + QTest::newRow("merged") << true; +} + +void tst_QProcess::setStandardOutputProcess() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QProcess source; + QProcess sink; + + QFETCH(bool, merged); + source.setReadChannelMode(merged ? QProcess::MergedChannels : QProcess::SeparateChannels); + source.setStandardOutputProcess(&sink); + +#ifdef Q_OS_MAC + source.start("testProcessEcho2/testProcessEcho2.app"); + sink.start("testProcessEcho2/testProcessEcho2.app"); +#else + source.start("testProcessEcho2/testProcessEcho2"); + sink.start("testProcessEcho2/testProcessEcho2"); +#endif + + QByteArray data("Hello, World"); + source.write(data); + source.closeWriteChannel(); + QPROCESS_VERIFY(source, waitForFinished()); + QPROCESS_VERIFY(sink, waitForFinished()); + QByteArray all = sink.readAll(); + + if (!merged) + QCOMPARE(all, data); + else + QCOMPARE(all, QByteArray("HHeelllloo,, WWoorrlldd")); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::fileWriterProcess() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + + QString stdinStr; + for (int i = 0; i < 5000; ++i) + stdinStr += QString::fromLatin1("%1 -- testing testing 1 2 3\n").arg(i); + + QTime stopWatch; + stopWatch.start(); + do { + QFile::remove("fileWriterProcess.txt"); + QProcess process; + process.start("fileWriterProcess/fileWriterProcess", + QIODevice::ReadWrite | QIODevice::Text); + process.write(stdinStr.toLatin1()); + process.closeWriteChannel(); + while (process.bytesToWrite()) { + QVERIFY(stopWatch.elapsed() < 3500); + QVERIFY(process.waitForBytesWritten(2000)); + } + QVERIFY(process.waitForFinished()); + QCOMPARE(QFile("fileWriterProcess.txt").size(), qint64(stdinStr.size())); + } while (stopWatch.elapsed() < 3000); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::detachedWorkingDirectoryAndPid() +{ +#if defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) + // WINSCW builds in Symbian do not allow multiple processes to load Qt libraries, + // so this test must be skipped. + QSKIP("Multiple processes loading Qt are not allowed in Qt/Symbian emulator.", SkipAll); +#endif + qint64 pid; + +#ifdef Q_OS_WINCE + QTest::qSleep(1000); +#endif + +#if defined(Q_OS_SYMBIAN) + // Symbian has no working directory support, so use logs dir as a shared directory + QFile infoFile(QLatin1String("c:\\logs\\detachedinfo.txt")); +#else + QFile infoFile(QDir::currentPath() + QLatin1String("/detachedinfo.txt")); +#endif + infoFile.remove(); + + QString workingDir = QDir::currentPath() + "/testDetached"; + +#ifndef Q_OS_SYMBIAN + QVERIFY(QFile::exists(workingDir)); +#endif + + QStringList args; + args << infoFile.fileName(); + QVERIFY(QProcess::startDetached(QDir::currentPath() + QLatin1String("/testDetached/testDetached"), args, workingDir, &pid)); + + QFileInfo fi(infoFile); + fi.setCaching(false); + while (fi.size() == 0) { + QTest::qSleep(100); + } + + QVERIFY(infoFile.open(QIODevice::ReadOnly | QIODevice::Text)); + QString actualWorkingDir = QString::fromUtf8(infoFile.readLine()); + actualWorkingDir.chop(1); // strip off newline + QByteArray processIdString = infoFile.readLine(); + processIdString.chop(1); + infoFile.close(); + infoFile.remove(); + + bool ok = false; + qint64 actualPid = processIdString.toLongLong(&ok); + QVERIFY(ok); + +#if defined(Q_OS_SYMBIAN) + QEXPECT_FAIL("", "Working directory is not supported on Qt/symbian", Continue); +#endif + QCOMPARE(actualWorkingDir, workingDir); + QCOMPARE(actualPid, pid); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::switchReadChannels() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll); +#endif + const char data[] = "ABCD"; + + QProcess process; + +#ifdef Q_OS_MAC + process.start("testProcessEcho2/testProcessEcho2.app"); +#else + process.start("testProcessEcho2/testProcessEcho2"); +#endif + process.write(data); + process.closeWriteChannel(); + QVERIFY(process.waitForFinished(5000)); + + for (int i = 0; i < 4; ++i) { + process.setReadChannel(QProcess::StandardOutput); + QCOMPARE(process.read(1), QByteArray(&data[i], 1)); + process.setReadChannel(QProcess::StandardError); + QCOMPARE(process.read(1), QByteArray(&data[i], 1)); + } + + process.ungetChar('D'); + process.setReadChannel(QProcess::StandardOutput); + process.ungetChar('D'); + process.setReadChannel(QProcess::StandardError); + QCOMPARE(process.read(1), QByteArray("D")); + process.setReadChannel(QProcess::StandardOutput); + QCOMPARE(process.read(1), QByteArray("D")); +} + +//----------------------------------------------------------------------------- +void tst_QProcess::setWorkingDirectory() +{ +#ifdef Q_OS_WINCE + QSKIP("Windows CE does not support working directory logic", SkipAll); +#endif +#if defined(Q_OS_SYMBIAN) + QSKIP("Symbian does not support working directory logic", SkipAll); +#endif + process = new QProcess; + process->setWorkingDirectory("test"); +#ifdef Q_OS_MAC + process->start("testSetWorkingDirectory/testSetWorkingDirectory.app"); +#else + process->start("testSetWorkingDirectory/testSetWorkingDirectory"); +#endif +#ifndef Q_OS_WIN + QSKIP("setWorkingDirectory will chdir before starting the process on unices", SkipAll); +#endif + QVERIFY(process->waitForFinished()); + + QByteArray workingDir = process->readAllStandardOutput(); + QCOMPARE(QDir("test").canonicalPath(), QDir(workingDir.constData()).canonicalPath()); + + delete process; + process = 0; +} + +//----------------------------------------------------------------------------- +void tst_QProcess::startFinishStartFinish() +{ + QProcess process; + + for (int i = 0; i < 3; ++i) { + QCOMPARE(process.state(), QProcess::NotRunning); + +#ifdef Q_OS_MAC + process.start("testProcessOutput/testProcessOutput.app"); +#else + process.start("testProcessOutput/testProcessOutput"); +#endif +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) + QVERIFY(process.waitForReadyRead(10000)); + QCOMPARE(QString::fromLatin1(process.readLine().trimmed()), + QString("0 -this is a number")); +#endif + if (process.state() != QProcess::NotRunning) + QVERIFY(process.waitForFinished(10000)); +#if defined(Q_OS_SYMBIAN) + // Symbian test outputs to a file, so check that + FILE* file = fopen("c:\\logs\\qprocess_output_test.txt","r"); + char buf[30]; + fgets(buf, 30, file); + QCOMPARE(QString::fromLatin1(buf), + QString("0 -this is a number\n")); + fclose(file); +#endif + } +} + +QTEST_MAIN(tst_QProcess) +#include "tst_qprocess.moc" |