tests/auto/qprocess/tst_qprocess.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 #include <QtCore/QProcess>
       
    45 #include <QtCore/QDir>
       
    46 #include <QtCore/QFile>
       
    47 #include <QtCore/QThread>
       
    48 #include <QtCore/QRegExp>
       
    49 #include <QtCore/QDebug>
       
    50 #include <QtCore/QMetaType>
       
    51 #if !defined(Q_OS_SYMBIAN)
       
    52 // Network test unnecessary?
       
    53 #include <QtNetwork/QHostInfo>
       
    54 #endif
       
    55 #include <stdlib.h>
       
    56 
       
    57 #ifdef QT_NO_PROCESS
       
    58 QTEST_NOOP_MAIN
       
    59 #else
       
    60 
       
    61 #if defined(Q_OS_WIN)
       
    62 #include <windows.h>
       
    63 #endif
       
    64 
       
    65 //TESTED_CLASS=
       
    66 //TESTED_FILES=
       
    67 
       
    68 Q_DECLARE_METATYPE(QList<QProcess::ExitStatus>);
       
    69 Q_DECLARE_METATYPE(QProcess::ExitStatus);
       
    70 Q_DECLARE_METATYPE(QProcess::ProcessState);
       
    71 
       
    72 #define QPROCESS_VERIFY(Process, Fn) \
       
    73 { \
       
    74 const bool ret = Process.Fn; \
       
    75 if (ret == false) \
       
    76 	qWarning("QProcess error: %d: %s", Process.error(), qPrintable(Process.errorString())); \
       
    77 QVERIFY(ret); \
       
    78 }
       
    79 
       
    80 class tst_QProcess : public QObject
       
    81 {
       
    82     Q_OBJECT
       
    83 
       
    84 public:
       
    85     tst_QProcess();
       
    86     virtual ~tst_QProcess();
       
    87 
       
    88 public slots:
       
    89     void init();
       
    90     void cleanup();
       
    91 
       
    92 private slots:
       
    93     void getSetCheck();
       
    94     void constructing();
       
    95     void simpleStart();
       
    96     void startDetached();
       
    97     void crashTest();
       
    98     void crashTest2();
       
    99     void echoTest_data();
       
   100     void echoTest();
       
   101     void echoTest2();
       
   102     void echoTest_performance();
       
   103 #if defined Q_OS_WIN
       
   104     void echoTestGui();
       
   105     void batFiles_data();
       
   106     void batFiles();
       
   107 #endif
       
   108     void exitStatus_data();
       
   109     void exitStatus();
       
   110     void loopBackTest();
       
   111     void readTimeoutAndThenCrash();
       
   112     void waitForFinished();
       
   113     void deadWhileReading();
       
   114     void restartProcessDeadlock();
       
   115     void closeWriteChannel();
       
   116     void closeReadChannel();
       
   117     void openModes();
       
   118     void emitReadyReadOnlyWhenNewDataArrives();
       
   119     void hardExit();
       
   120     void softExit();
       
   121     void softExitInSlots_data();
       
   122     void softExitInSlots();
       
   123     void mergedChannels();
       
   124     void forwardedChannels();
       
   125     void atEnd();
       
   126     void atEnd2();
       
   127     void processInAThread();
       
   128     void processesInMultipleThreads();
       
   129     void waitForFinishedWithTimeout();
       
   130     void waitForReadyReadInAReadyReadSlot();
       
   131     void waitForBytesWrittenInABytesWrittenSlot();
       
   132     void spaceArgsTest_data();
       
   133     void spaceArgsTest();
       
   134     void exitCodeTest();
       
   135     void setEnvironment_data();
       
   136     void setEnvironment();
       
   137     void setProcessEnvironment_data();
       
   138     void setProcessEnvironment();
       
   139     void systemEnvironment();
       
   140     void spaceInName();
       
   141     void lockupsInStartDetached();
       
   142     void waitForReadyReadForNonexistantProcess();
       
   143     void setStandardInputFile();
       
   144     void setStandardOutputFile_data();
       
   145     void setStandardOutputFile();
       
   146     void setStandardOutputProcess_data();
       
   147     void setStandardOutputProcess();
       
   148     void removeFileWhileProcessIsRunning();
       
   149     void fileWriterProcess();
       
   150     void detachedWorkingDirectoryAndPid();
       
   151     void switchReadChannels();
       
   152     void setWorkingDirectory();
       
   153     void startFinishStartFinish();
       
   154     void invalidProgramString_data();
       
   155     void invalidProgramString();
       
   156 
       
   157     // keep these at the end, since they use lots of processes and sometimes
       
   158     // caused obscure failures to occur in tests that followed them (esp. on the Mac)
       
   159     void failToStart();
       
   160     void failToStartWithWait();
       
   161     void failToStartWithEventLoop();
       
   162 
       
   163 protected slots:
       
   164     void readFromProcess();
       
   165     void exitLoopSlot();
       
   166     void restartProcess();
       
   167     void waitForReadyReadInAReadyReadSlotSlot();
       
   168     void waitForBytesWrittenInABytesWrittenSlotSlot();
       
   169 
       
   170 private:
       
   171     QProcess *process;
       
   172     qint64 bytesAvailable;
       
   173 };
       
   174 
       
   175 // Testing get/set functions
       
   176 void tst_QProcess::getSetCheck()
       
   177 {
       
   178     QProcess obj1;
       
   179     // ProcessChannelMode QProcess::readChannelMode()
       
   180     // void QProcess::setReadChannelMode(ProcessChannelMode)
       
   181     obj1.setReadChannelMode(QProcess::ProcessChannelMode(QProcess::SeparateChannels));
       
   182     QCOMPARE(QProcess::ProcessChannelMode(QProcess::SeparateChannels), obj1.readChannelMode());
       
   183     obj1.setReadChannelMode(QProcess::ProcessChannelMode(QProcess::MergedChannels));
       
   184     QCOMPARE(QProcess::ProcessChannelMode(QProcess::MergedChannels), obj1.readChannelMode());
       
   185     obj1.setReadChannelMode(QProcess::ProcessChannelMode(QProcess::ForwardedChannels));
       
   186     QCOMPARE(QProcess::ProcessChannelMode(QProcess::ForwardedChannels), obj1.readChannelMode());
       
   187 
       
   188     // ProcessChannel QProcess::readChannel()
       
   189     // void QProcess::setReadChannel(ProcessChannel)
       
   190     obj1.setReadChannel(QProcess::ProcessChannel(QProcess::StandardOutput));
       
   191     QCOMPARE(QProcess::ProcessChannel(QProcess::StandardOutput), obj1.readChannel());
       
   192     obj1.setReadChannel(QProcess::ProcessChannel(QProcess::StandardError));
       
   193     QCOMPARE(QProcess::ProcessChannel(QProcess::StandardError), obj1.readChannel());
       
   194 }
       
   195 
       
   196 tst_QProcess::tst_QProcess()
       
   197 {
       
   198 }
       
   199 
       
   200 tst_QProcess::~tst_QProcess()
       
   201 {
       
   202 }
       
   203 
       
   204 void tst_QProcess::init()
       
   205 {
       
   206 #ifdef Q_OS_SYMBIAN
       
   207     QString dirStr = QString::fromLatin1("c:\\logs");
       
   208     QDir dir;
       
   209     if (!dir.exists(dirStr))
       
   210         dir.mkpath(dirStr);
       
   211 #endif
       
   212 }
       
   213 
       
   214 void tst_QProcess::cleanup()
       
   215 {
       
   216 }
       
   217 
       
   218 //-----------------------------------------------------------------------------
       
   219 void tst_QProcess::constructing()
       
   220 {
       
   221     QProcess process;
       
   222     QCOMPARE(process.readChannel(), QProcess::StandardOutput);
       
   223     QCOMPARE(process.workingDirectory(), QString());
       
   224     QCOMPARE(process.environment(), QStringList());
       
   225     QCOMPARE(process.error(), QProcess::UnknownError);
       
   226     QCOMPARE(process.state(), QProcess::NotRunning);
       
   227     QCOMPARE(process.pid(), Q_PID(0));
       
   228     QCOMPARE(process.readAllStandardOutput(), QByteArray());
       
   229     QCOMPARE(process.readAllStandardError(), QByteArray());
       
   230     QCOMPARE(process.canReadLine(), false);
       
   231 
       
   232     // QIODevice
       
   233     QCOMPARE(process.openMode(), QIODevice::NotOpen);
       
   234     QVERIFY(!process.isOpen());
       
   235     QVERIFY(!process.isReadable());
       
   236     QVERIFY(!process.isWritable());
       
   237     QVERIFY(process.isSequential());
       
   238     QCOMPARE(process.pos(), qlonglong(0));
       
   239     QCOMPARE(process.size(), qlonglong(0));
       
   240     QVERIFY(process.atEnd());
       
   241     QCOMPARE(process.bytesAvailable(), qlonglong(0));
       
   242     QCOMPARE(process.bytesToWrite(), qlonglong(0));
       
   243     QVERIFY(!process.errorString().isEmpty());
       
   244 
       
   245     char c;
       
   246     QCOMPARE(process.read(&c, 1), qlonglong(-1));
       
   247     QCOMPARE(process.write(&c, 1), qlonglong(-1));
       
   248 }
       
   249 
       
   250 void tst_QProcess::simpleStart()
       
   251 {
       
   252     qRegisterMetaType<QProcess::ProcessState>("QProcess::ProcessState");
       
   253 
       
   254     process = new QProcess;
       
   255     QSignalSpy spy(process, SIGNAL(stateChanged(QProcess::ProcessState)));
       
   256     connect(process, SIGNAL(readyRead()), this, SLOT(readFromProcess()));
       
   257 
       
   258     /* valgrind dislike SUID binaries(those that have the `s'-flag set), which
       
   259      * makes it fail to start the process. For this reason utilities like `ping' won't
       
   260      * start, when the auto test is run through `valgrind'. */
       
   261     process->start("testProcessNormal/testProcessNormal");
       
   262     if (process->state() != QProcess::Starting)
       
   263         QCOMPARE(process->state(), QProcess::Running);
       
   264     QVERIFY(process->waitForStarted(5000));
       
   265     QCOMPARE(process->state(), QProcess::Running);
       
   266 #if defined(Q_OS_WINCE)
       
   267     // Note: This actually seems incorrect, it will only exit the while loop when finishing fails
       
   268     while (process->waitForFinished(5000))
       
   269     { }
       
   270 #elif defined(Q_OS_SYMBIAN)
       
   271     QVERIFY(process->waitForFinished(5000));
       
   272 #else
       
   273     while (process->waitForReadyRead(5000))
       
   274     { }
       
   275 #endif
       
   276     QCOMPARE(process->state(), QProcess::NotRunning);
       
   277 
       
   278     delete process;
       
   279     process = 0;
       
   280 
       
   281     QCOMPARE(spy.count(), 3);
       
   282     QCOMPARE(qVariantValue<QProcess::ProcessState>(spy.at(0).at(0)), QProcess::Starting);
       
   283     QCOMPARE(qVariantValue<QProcess::ProcessState>(spy.at(1).at(0)), QProcess::Running);
       
   284     QCOMPARE(qVariantValue<QProcess::ProcessState>(spy.at(2).at(0)), QProcess::NotRunning);
       
   285 }
       
   286 //-----------------------------------------------------------------------------
       
   287 void tst_QProcess::startDetached()
       
   288 {
       
   289     QProcess proc;
       
   290     QVERIFY(proc.startDetached("testProcessNormal/testProcessNormal",
       
   291                                QStringList() << "arg1" << "arg2"));
       
   292     QCOMPARE(QProcess::startDetached("nonexistingexe"), false);
       
   293 }
       
   294 
       
   295 //-----------------------------------------------------------------------------
       
   296 void tst_QProcess::readFromProcess()
       
   297 {
       
   298     int lines = 0;
       
   299     while (process->canReadLine()) {
       
   300         ++lines;
       
   301         QByteArray line = process->readLine();
       
   302     }
       
   303 }
       
   304 
       
   305 //-----------------------------------------------------------------------------
       
   306 void tst_QProcess::crashTest()
       
   307 {
       
   308     qRegisterMetaType<QProcess::ProcessState>("QProcess::ProcessState");
       
   309 #ifdef Q_OS_WIN
       
   310     QSKIP("This test opens a crash dialog on Windows", SkipSingle);
       
   311 #endif
       
   312     process = new QProcess;
       
   313     QSignalSpy stateSpy(process, SIGNAL(stateChanged(QProcess::ProcessState)));
       
   314     process->start("testProcessCrash/testProcessCrash");
       
   315     QVERIFY(process->waitForStarted(5000));
       
   316 
       
   317     qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
       
   318     qRegisterMetaType<QProcess::ProcessError>("QProcess::ExitStatus");
       
   319 
       
   320     QSignalSpy spy(process, SIGNAL(error(QProcess::ProcessError)));
       
   321     QSignalSpy spy2(process, SIGNAL(finished(int, QProcess::ExitStatus)));
       
   322 
       
   323     QVERIFY(process->waitForFinished(5000));
       
   324 
       
   325     QCOMPARE(spy.count(), 1);
       
   326     QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed);
       
   327 
       
   328     QCOMPARE(spy2.count(), 1);
       
   329     QCOMPARE(*static_cast<const QProcess::ExitStatus *>(spy2.at(0).at(1).constData()), QProcess::CrashExit);
       
   330 
       
   331     QCOMPARE(process->exitStatus(), QProcess::CrashExit);
       
   332 
       
   333     delete process;
       
   334     process = 0;
       
   335 
       
   336     QCOMPARE(stateSpy.count(), 3);
       
   337     QCOMPARE(qVariantValue<QProcess::ProcessState>(stateSpy.at(0).at(0)), QProcess::Starting);
       
   338     QCOMPARE(qVariantValue<QProcess::ProcessState>(stateSpy.at(1).at(0)), QProcess::Running);
       
   339     QCOMPARE(qVariantValue<QProcess::ProcessState>(stateSpy.at(2).at(0)), QProcess::NotRunning);
       
   340 }
       
   341 
       
   342 //-----------------------------------------------------------------------------
       
   343 void tst_QProcess::crashTest2()
       
   344 {
       
   345 #ifdef Q_OS_WIN
       
   346     QSKIP("This test opens a crash dialog on Windows", SkipSingle);
       
   347 #endif
       
   348     process = new QProcess;
       
   349     process->start("testProcessCrash/testProcessCrash");
       
   350     QVERIFY(process->waitForStarted(5000));
       
   351 
       
   352     qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
       
   353     qRegisterMetaType<QProcess::ProcessError>("QProcess::ExitStatus");
       
   354 
       
   355     QSignalSpy spy(process, SIGNAL(error(QProcess::ProcessError)));
       
   356     QSignalSpy spy2(process, SIGNAL(finished(int, QProcess::ExitStatus)));
       
   357 
       
   358     QObject::connect(process, SIGNAL(finished(int)), this, SLOT(exitLoopSlot()));
       
   359 
       
   360     QTestEventLoop::instance().enterLoop(5);
       
   361     if (QTestEventLoop::instance().timeout())
       
   362         QFAIL("Failed to detect crash : operation timed out");
       
   363 
       
   364     QCOMPARE(spy.count(), 1);
       
   365     QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed);
       
   366 
       
   367     QCOMPARE(spy2.count(), 1);
       
   368     QCOMPARE(*static_cast<const QProcess::ExitStatus *>(spy2.at(0).at(1).constData()), QProcess::CrashExit);
       
   369 
       
   370     QCOMPARE(process->exitStatus(), QProcess::CrashExit);
       
   371 
       
   372     delete process;
       
   373     process = 0;
       
   374 }
       
   375 
       
   376 //-----------------------------------------------------------------------------
       
   377 void tst_QProcess::echoTest_data()
       
   378 {
       
   379     QTest::addColumn<QByteArray>("input");
       
   380 
       
   381     QTest::newRow("1") << QByteArray("H");
       
   382     QTest::newRow("2") << QByteArray("He");
       
   383     QTest::newRow("3") << QByteArray("Hel");
       
   384     QTest::newRow("4") << QByteArray("Hell");
       
   385     QTest::newRow("5") << QByteArray("Hello");
       
   386     QTest::newRow("100 bytes") << QByteArray(100, '@');
       
   387     QTest::newRow("1000 bytes") << QByteArray(1000, '@');
       
   388     QTest::newRow("10000 bytes") << QByteArray(10000, '@');
       
   389 }
       
   390 
       
   391 //-----------------------------------------------------------------------------
       
   392 void tst_QProcess::echoTest()
       
   393 {
       
   394 #ifdef Q_OS_WINCE
       
   395     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   396 #endif
       
   397 #if defined(Q_OS_SYMBIAN)
       
   398     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   399 #endif
       
   400 
       
   401     QFETCH(QByteArray, input);
       
   402 
       
   403     process = new QProcess;
       
   404     connect(process, SIGNAL(readyRead()), this, SLOT(exitLoopSlot()));
       
   405 
       
   406 #ifdef Q_OS_MAC
       
   407     process->start("testProcessEcho/testProcessEcho.app");
       
   408 #else
       
   409     process->start("testProcessEcho/testProcessEcho");
       
   410 #endif
       
   411     QVERIFY(process->waitForStarted(5000));
       
   412 
       
   413     process->write(input);
       
   414 
       
   415     QTime stopWatch;
       
   416     stopWatch.start();
       
   417     do {
       
   418         QVERIFY(process->isOpen());
       
   419         QTestEventLoop::instance().enterLoop(2);
       
   420     } while (stopWatch.elapsed() < 60000 && process->bytesAvailable() < input.size());
       
   421     if (stopWatch.elapsed() >= 60000)
       
   422         QFAIL("Timed out");
       
   423 
       
   424     QByteArray message = process->readAll();
       
   425     QCOMPARE(message.size(), input.size());
       
   426 
       
   427     char *c1 = message.data();
       
   428     char *c2 = input.data();
       
   429     while (*c1 && *c2) {
       
   430         if (*c1 != *c2)
       
   431             QCOMPARE(*c1, *c2);
       
   432         ++c1;
       
   433         ++c2;
       
   434     }
       
   435     QCOMPARE(*c1, *c2);
       
   436 
       
   437     process->write("", 1);
       
   438 
       
   439     QVERIFY(process->waitForFinished(5000));
       
   440 
       
   441 
       
   442     delete process;
       
   443     process = 0;
       
   444 }
       
   445 
       
   446 //-----------------------------------------------------------------------------
       
   447 void tst_QProcess::exitLoopSlot()
       
   448 {
       
   449     QTestEventLoop::instance().exitLoop();
       
   450 }
       
   451 
       
   452 //-----------------------------------------------------------------------------
       
   453 void tst_QProcess::echoTest2()
       
   454 {
       
   455 #ifdef Q_OS_WINCE
       
   456     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   457 #endif
       
   458 #if defined(Q_OS_SYMBIAN)
       
   459     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   460 #endif
       
   461 
       
   462     process = new QProcess;
       
   463     connect(process, SIGNAL(readyRead()), this, SLOT(exitLoopSlot()));
       
   464 
       
   465 #ifdef Q_OS_MAC
       
   466     process->start("testProcessEcho2/testProcessEcho2.app");
       
   467 #else
       
   468     process->start("testProcessEcho2/testProcessEcho2");
       
   469 #endif
       
   470     QVERIFY(process->waitForStarted(5000));
       
   471     QVERIFY(!process->waitForReadyRead(250));
       
   472     QCOMPARE(process->error(), QProcess::Timedout);
       
   473 
       
   474     process->write("Hello");
       
   475     QSignalSpy spy1(process, SIGNAL(readyReadStandardOutput()));
       
   476     QSignalSpy spy2(process, SIGNAL(readyReadStandardError()));
       
   477 
       
   478     QTime stopWatch;
       
   479     stopWatch.start();
       
   480     forever {
       
   481         QTestEventLoop::instance().enterLoop(1);
       
   482         if (stopWatch.elapsed() >= 30000)
       
   483             QFAIL("Timed out");
       
   484         process->setReadChannel(QProcess::StandardOutput);
       
   485         qint64 baso = process->bytesAvailable();
       
   486 
       
   487         process->setReadChannel(QProcess::StandardError);
       
   488         qint64 base = process->bytesAvailable();
       
   489         if (baso == 5 && base == 5)
       
   490             break;
       
   491     }
       
   492 
       
   493     QVERIFY(spy1.count() > 0);
       
   494     QVERIFY(spy2.count() > 0);
       
   495 
       
   496     QCOMPARE(process->readAllStandardOutput(), QByteArray("Hello"));
       
   497     QCOMPARE(process->readAllStandardError(), QByteArray("Hello"));
       
   498 
       
   499     process->write("", 1);
       
   500     QVERIFY(process->waitForFinished(5000));
       
   501 
       
   502     delete process;
       
   503     process = 0;
       
   504 }
       
   505 
       
   506 //-----------------------------------------------------------------------------
       
   507 void tst_QProcess::echoTest_performance()
       
   508 {
       
   509 #ifdef Q_OS_WINCE
       
   510     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   511 #endif
       
   512 #if defined(Q_OS_SYMBIAN)
       
   513     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   514 #endif
       
   515 
       
   516     QProcess process;
       
   517 #ifdef Q_OS_MAC
       
   518     process.start("testProcessLoopback/testProcessLoopback.app");
       
   519 #else
       
   520     process.start("testProcessLoopback/testProcessLoopback");
       
   521 #endif
       
   522 
       
   523     QByteArray array;
       
   524     array.resize(1024 * 1024);
       
   525     for (int j = 0; j < array.size(); ++j)
       
   526         array[j] = 'a' + (j % 20);
       
   527 
       
   528     QVERIFY(process.waitForStarted());
       
   529 
       
   530     QTime stopWatch;
       
   531     stopWatch.start();
       
   532 
       
   533     qint64 totalBytes = 0;
       
   534     QByteArray dump;
       
   535     QSignalSpy readyReadSpy(&process, SIGNAL(readyRead()));
       
   536     while (stopWatch.elapsed() < 2000) {
       
   537         process.write(array);
       
   538         while (process.bytesToWrite() > 0) {
       
   539             int readCount = readyReadSpy.count();
       
   540             QVERIFY(process.waitForBytesWritten(5000));
       
   541             if (readyReadSpy.count() == readCount)
       
   542                 QVERIFY(process.waitForReadyRead(5000));
       
   543         }
       
   544 
       
   545         while (process.bytesAvailable() < array.size())
       
   546             QVERIFY2(process.waitForReadyRead(5000), qPrintable(process.errorString()));
       
   547         dump = process.readAll();
       
   548         totalBytes += dump.size();
       
   549     }
       
   550 
       
   551     qDebug() << "Elapsed time:" << stopWatch.elapsed() << "ms;"
       
   552              << "transfer rate:" << totalBytes / (1048.576) / stopWatch.elapsed()
       
   553              << "MB/s";
       
   554 
       
   555     for (int j = 0; j < array.size(); ++j)
       
   556         QCOMPARE(char(dump.at(j)), char('a' + (j % 20)));
       
   557 
       
   558     process.closeWriteChannel();
       
   559     QVERIFY(process.waitForFinished());
       
   560 }
       
   561 
       
   562 #if defined Q_OS_WIN
       
   563 //-----------------------------------------------------------------------------
       
   564 void tst_QProcess::echoTestGui()
       
   565 {
       
   566 #ifdef Q_OS_WINCE
       
   567     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   568 #endif
       
   569 #if defined(Q_OS_SYMBIAN)
       
   570     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   571 #endif
       
   572 
       
   573     QProcess process;
       
   574 
       
   575     process.start("testProcessEchoGui/testProcessEchoGui");
       
   576 
       
   577 
       
   578     process.write("Hello");
       
   579     process.write("q");
       
   580 
       
   581     QVERIFY(process.waitForFinished(50000));
       
   582 
       
   583     QCOMPARE(process.readAllStandardOutput(), QByteArray("Hello"));
       
   584     QCOMPARE(process.readAllStandardError(), QByteArray("Hello"));
       
   585 }
       
   586 
       
   587 //-----------------------------------------------------------------------------
       
   588 void tst_QProcess::batFiles_data()
       
   589 {
       
   590     QTest::addColumn<QString>("batFile");
       
   591     QTest::addColumn<QByteArray>("output");
       
   592 
       
   593     QTest::newRow("simple") << QString::fromLatin1("testBatFiles/simple.bat") << QByteArray("Hello");
       
   594     QTest::newRow("with space") << QString::fromLatin1("testBatFiles/with space.bat") << QByteArray("Hello");
       
   595 }
       
   596 
       
   597 void tst_QProcess::batFiles()
       
   598 {
       
   599 #if defined(Q_OS_WINCE)
       
   600     QSKIP("Batch files are not supported on Windows CE", SkipAll);
       
   601 #endif
       
   602 #if defined(Q_OS_SYMBIAN)
       
   603     QSKIP("Batch files are not supported on Symbian", SkipAll);
       
   604 #endif
       
   605     QFETCH(QString, batFile);
       
   606     QFETCH(QByteArray, output);
       
   607 
       
   608     QProcess proc;
       
   609 
       
   610     proc.start(batFile, QStringList());
       
   611 
       
   612     QVERIFY(proc.waitForFinished(5000));
       
   613 
       
   614     QVERIFY(proc.bytesAvailable() > 0);
       
   615 
       
   616     QVERIFY(proc.readAll().startsWith(output));
       
   617 }
       
   618 
       
   619 #endif
       
   620 
       
   621 //-----------------------------------------------------------------------------
       
   622 void tst_QProcess::exitStatus_data()
       
   623 {
       
   624     QTest::addColumn<QStringList>("processList");
       
   625     QTest::addColumn<QList<QProcess::ExitStatus> >("exitStatus");
       
   626 
       
   627     QTest::newRow("normal") << (QStringList() << "testProcessNormal/testProcessNormal")
       
   628                             << (QList<QProcess::ExitStatus>() << QProcess::NormalExit);
       
   629     QTest::newRow("crash") << (QStringList() << "testProcessCrash/testProcessCrash")
       
   630                             << (QList<QProcess::ExitStatus>() << QProcess::CrashExit);
       
   631 
       
   632     QTest::newRow("normal-crash") << (QStringList()
       
   633                                       << "testProcessNormal/testProcessNormal"
       
   634                                       << "testProcessCrash/testProcessCrash")
       
   635                                   << (QList<QProcess::ExitStatus>()
       
   636                                       << QProcess::NormalExit
       
   637                                       << QProcess::CrashExit);
       
   638     QTest::newRow("crash-normal") << (QStringList()
       
   639                                       << "testProcessCrash/testProcessCrash"
       
   640                                       << "testProcessNormal/testProcessNormal")
       
   641                                   << (QList<QProcess::ExitStatus>()
       
   642                                       << QProcess::CrashExit
       
   643                                       << QProcess::NormalExit);
       
   644 }
       
   645 
       
   646 void tst_QProcess::exitStatus()
       
   647 {
       
   648     process = new QProcess;
       
   649     QFETCH(QStringList, processList);
       
   650     QFETCH(QList<QProcess::ExitStatus>, exitStatus);
       
   651 
       
   652 #ifdef Q_OS_WIN
       
   653     if (exitStatus.contains(QProcess::CrashExit))
       
   654         QSKIP("This test opens a crash dialog on Windows", SkipSingle);
       
   655 #endif
       
   656 
       
   657     Q_ASSERT(processList.count() == exitStatus.count());
       
   658     for (int i = 0; i < processList.count(); ++i) {
       
   659         process->start(processList.at(i));
       
   660         QVERIFY(process->waitForStarted(5000));
       
   661         QVERIFY(process->waitForFinished(5000));
       
   662 
       
   663         QCOMPARE(process->exitStatus(), exitStatus.at(i));
       
   664     }
       
   665 
       
   666     process->deleteLater();
       
   667     process = 0;
       
   668 }
       
   669 //-----------------------------------------------------------------------------
       
   670 void tst_QProcess::loopBackTest()
       
   671 {
       
   672 #ifdef Q_OS_WINCE
       
   673     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   674 #endif
       
   675 #if defined(Q_OS_SYMBIAN)
       
   676     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   677 #endif
       
   678 
       
   679     process = new QProcess;
       
   680 #ifdef Q_OS_MAC
       
   681     process->start("testProcessEcho/testProcessEcho.app");
       
   682 #else
       
   683     process->start("testProcessEcho/testProcessEcho");
       
   684 #endif
       
   685     QVERIFY(process->waitForStarted(5000));
       
   686 
       
   687     for (int i = 0; i < 100; ++i) {
       
   688         process->write("Hello");
       
   689         do {
       
   690             QVERIFY(process->waitForReadyRead(5000));
       
   691         } while (process->bytesAvailable() < 5);
       
   692         QCOMPARE(process->readAll(), QByteArray("Hello"));
       
   693     }
       
   694 
       
   695     process->write("", 1);
       
   696     QVERIFY(process->waitForFinished(5000));
       
   697 
       
   698     delete process;
       
   699     process = 0;
       
   700 }
       
   701 
       
   702 //-----------------------------------------------------------------------------
       
   703 void tst_QProcess::readTimeoutAndThenCrash()
       
   704 {
       
   705 #ifdef Q_OS_WINCE
       
   706     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   707 #endif
       
   708 #if defined(Q_OS_SYMBIAN)
       
   709     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   710 #endif
       
   711 
       
   712     process = new QProcess;
       
   713 #ifdef Q_OS_MAC
       
   714     process->start("testProcessEcho/testProcessEcho.app");
       
   715 #else
       
   716     process->start("testProcessEcho/testProcessEcho");
       
   717 #endif
       
   718     if (process->state() != QProcess::Starting)
       
   719         QCOMPARE(process->state(), QProcess::Running);
       
   720 
       
   721     QVERIFY(process->waitForStarted(5000));
       
   722     QCOMPARE(process->state(), QProcess::Running);
       
   723 
       
   724     QVERIFY(!process->waitForReadyRead(5000));
       
   725     QCOMPARE(process->error(), QProcess::Timedout);
       
   726 
       
   727     qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
       
   728     QSignalSpy spy(process, SIGNAL(error(QProcess::ProcessError)));
       
   729 
       
   730     process->kill();
       
   731 
       
   732     QVERIFY(process->waitForFinished(5000));
       
   733     QCOMPARE(process->state(), QProcess::NotRunning);
       
   734 
       
   735     QCOMPARE(spy.count(), 1);
       
   736     QCOMPARE(*static_cast<const QProcess::ProcessError *>(spy.at(0).at(0).constData()), QProcess::Crashed);
       
   737 
       
   738     delete process;
       
   739     process = 0;
       
   740 }
       
   741 
       
   742 void tst_QProcess::waitForFinished()
       
   743 {
       
   744     QProcess process;
       
   745 
       
   746 #ifdef Q_OS_MAC
       
   747     process.start("testProcessOutput/testProcessOutput.app");
       
   748 #else
       
   749     process.start("testProcessOutput/testProcessOutput");
       
   750 #endif
       
   751 
       
   752 #if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
       
   753     QVERIFY(process.waitForFinished(5000));
       
   754 #else
       
   755     QVERIFY(process.waitForFinished(30000));
       
   756 #endif
       
   757     QCOMPARE(process.exitStatus(), QProcess::NormalExit);
       
   758 
       
   759 #if defined(Q_OS_SYMBIAN)
       
   760     // Symbian test outputs to a file, so check that
       
   761     FILE* file = fopen("c:\\logs\\qprocess_output_test.txt","r");
       
   762     int retval = 0;
       
   763     int count = 0;
       
   764     while((int)(retval = fgetc(file) )!= EOF)
       
   765         if (retval == '\n')
       
   766             count++;
       
   767     fclose(file);
       
   768     QCOMPARE(count, 200);
       
   769 #else
       
   770 #  if defined (Q_OS_WINCE)
       
   771     QEXPECT_FAIL("", "Reading and writing to a process is not supported on Qt/CE", Continue);
       
   772 #  endif
       
   773     QString output = process.readAll();
       
   774     QCOMPARE(output.count("\n"), 10*1024);
       
   775 #endif
       
   776 
       
   777     process.start("blurdybloop");
       
   778     QVERIFY(!process.waitForFinished());
       
   779     QCOMPARE(process.error(), QProcess::FailedToStart);
       
   780 }
       
   781 
       
   782 
       
   783 void tst_QProcess::deadWhileReading()
       
   784 {
       
   785 #ifdef Q_OS_WINCE
       
   786     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   787 #endif
       
   788 #if defined(Q_OS_SYMBIAN)
       
   789     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   790 #endif
       
   791 
       
   792     QProcess process;
       
   793 
       
   794 #ifdef Q_OS_MAC
       
   795     process.start("testProcessDeadWhileReading/testProcessDeadWhileReading.app");
       
   796 #else
       
   797     process.start("testProcessDeadWhileReading/testProcessDeadWhileReading");
       
   798 #endif
       
   799 
       
   800     QString output;
       
   801 
       
   802     QVERIFY(process.waitForStarted(5000));
       
   803     while (process.waitForReadyRead(5000))
       
   804         output += process.readAll();
       
   805 
       
   806     QCOMPARE(output.count("\n"), 10*1024);
       
   807     process.waitForFinished();
       
   808 }
       
   809 
       
   810 //-----------------------------------------------------------------------------
       
   811 void tst_QProcess::restartProcessDeadlock()
       
   812 {
       
   813 #ifdef Q_OS_WINCE
       
   814     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   815 #endif
       
   816 #if defined(Q_OS_SYMBIAN)
       
   817     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   818 #endif
       
   819 
       
   820     // The purpose of this test is to detect whether restarting a
       
   821     // process in the finished() connected slot causes a deadlock
       
   822     // because of the way QProcessManager uses its locks.
       
   823     QProcess proc;
       
   824     process = &proc;
       
   825     connect(process, SIGNAL(finished(int)), this, SLOT(restartProcess()));
       
   826 
       
   827 #ifdef Q_OS_MAC
       
   828     process->start("testProcessEcho/testProcessEcho.app");
       
   829 #else
       
   830     process->start("testProcessEcho/testProcessEcho");
       
   831 #endif
       
   832 
       
   833     QCOMPARE(process->write("", 1), qlonglong(1));
       
   834     QVERIFY(process->waitForFinished(5000));
       
   835 
       
   836     process->disconnect(SIGNAL(finished(int)));
       
   837 
       
   838     QCOMPARE(process->write("", 1), qlonglong(1));
       
   839     QVERIFY(process->waitForFinished(5000));
       
   840 }
       
   841 
       
   842 void tst_QProcess::restartProcess()
       
   843 {
       
   844 #ifdef Q_OS_MAC
       
   845     process->start("testProcessEcho/testProcessEcho.app");
       
   846 #else
       
   847     process->start("testProcessEcho/testProcessEcho");
       
   848 #endif
       
   849 }
       
   850 
       
   851 //-----------------------------------------------------------------------------
       
   852 void tst_QProcess::closeWriteChannel()
       
   853 {
       
   854 #ifdef Q_OS_WINCE
       
   855     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   856 #endif
       
   857 #if defined(Q_OS_SYMBIAN)
       
   858     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   859 #endif
       
   860 
       
   861     QProcess more;
       
   862     more.start("testProcessEOF/testProcessEOF");
       
   863 
       
   864     QVERIFY(more.waitForStarted(5000));
       
   865     QVERIFY(!more.waitForReadyRead(250));
       
   866     QCOMPARE(more.error(), QProcess::Timedout);
       
   867 
       
   868     QVERIFY(more.write("Data to read") != -1);
       
   869 
       
   870     QVERIFY(!more.waitForReadyRead(250));
       
   871     QCOMPARE(more.error(), QProcess::Timedout);
       
   872 
       
   873     more.closeWriteChannel();
       
   874 
       
   875     QVERIFY(more.waitForReadyRead(5000));
       
   876     QVERIFY(more.readAll().startsWith("Data to read"));
       
   877 
       
   878     if (more.state() == QProcess::Running)
       
   879         more.write("q");
       
   880     QVERIFY(more.waitForFinished(5000));
       
   881 }
       
   882 
       
   883 //-----------------------------------------------------------------------------
       
   884 void tst_QProcess::closeReadChannel()
       
   885 {
       
   886 #ifdef Q_OS_WINCE
       
   887     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   888 #endif
       
   889 #if defined(Q_OS_SYMBIAN)
       
   890     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   891 #endif
       
   892 
       
   893     for (int i = 0; i < 10; ++i) {
       
   894         QProcess::ProcessChannel channel1 = QProcess::StandardOutput;
       
   895         QProcess::ProcessChannel channel2 = QProcess::StandardError;
       
   896 
       
   897         QProcess proc;
       
   898 #ifdef Q_OS_MAC
       
   899         proc.start("testProcessEcho2/testProcessEcho2.app");
       
   900 #else
       
   901         proc.start("testProcessEcho2/testProcessEcho2");
       
   902 #endif
       
   903         QVERIFY(proc.waitForStarted(5000));
       
   904         proc.closeReadChannel(i&1 ? channel2 : channel1);
       
   905         proc.setReadChannel(i&1 ? channel2 : channel1);
       
   906         proc.write("Data");
       
   907 
       
   908         QVERIFY(!proc.waitForReadyRead(5000));
       
   909         QVERIFY(proc.readAll().isEmpty());
       
   910 
       
   911         proc.setReadChannel(i&1 ? channel1 : channel2);
       
   912 
       
   913         while (proc.bytesAvailable() < 4 && proc.waitForReadyRead(5000))
       
   914         { }
       
   915 
       
   916         QCOMPARE(proc.readAll(), QByteArray("Data"));
       
   917 
       
   918         proc.write("", 1);
       
   919         QVERIFY(proc.waitForFinished(5000));
       
   920     }
       
   921 }
       
   922 
       
   923 //-----------------------------------------------------------------------------
       
   924 void tst_QProcess::openModes()
       
   925 {
       
   926 #ifdef Q_OS_WINCE
       
   927     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   928 #endif
       
   929 #if defined(Q_OS_SYMBIAN)
       
   930     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   931 #endif
       
   932 
       
   933     QProcess proc;
       
   934     QVERIFY(!proc.isOpen());
       
   935     QVERIFY(proc.openMode() == QProcess::NotOpen);
       
   936 #ifdef Q_OS_MAC
       
   937     proc.start("testProcessEcho3/testProcessEcho3.app");
       
   938 #else
       
   939     proc.start("testProcessEcho3/testProcessEcho3");
       
   940 #endif
       
   941     QVERIFY(proc.waitForStarted(5000));
       
   942     QVERIFY(proc.isOpen());
       
   943     QVERIFY(proc.openMode() == QProcess::ReadWrite);
       
   944     QVERIFY(proc.isReadable());
       
   945     QVERIFY(proc.isWritable());
       
   946 
       
   947     proc.write("Data");
       
   948 
       
   949     proc.closeWriteChannel();
       
   950 
       
   951     QVERIFY(proc.isWritable());
       
   952     QVERIFY(proc.openMode() == QProcess::ReadWrite);
       
   953 
       
   954     while (proc.bytesAvailable() < 4 && proc.waitForReadyRead(5000))
       
   955     { }
       
   956 
       
   957     QCOMPARE(proc.readAll().constData(), QByteArray("Data").constData());
       
   958 
       
   959     proc.closeReadChannel(QProcess::StandardOutput);
       
   960 
       
   961     QVERIFY(proc.openMode() == QProcess::ReadWrite);
       
   962     QVERIFY(proc.isReadable());
       
   963 
       
   964     proc.closeReadChannel(QProcess::StandardError);
       
   965 
       
   966     QVERIFY(proc.openMode() == QProcess::ReadWrite);
       
   967     QVERIFY(proc.isReadable());
       
   968 
       
   969     proc.close();
       
   970     QVERIFY(!proc.isOpen());
       
   971     QVERIFY(!proc.isReadable());
       
   972     QVERIFY(!proc.isWritable());
       
   973     QCOMPARE(proc.state(), QProcess::NotRunning);
       
   974 }
       
   975 
       
   976 //-----------------------------------------------------------------------------
       
   977 void tst_QProcess::emitReadyReadOnlyWhenNewDataArrives()
       
   978 {
       
   979 #ifdef Q_OS_WINCE
       
   980     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
   981 #endif
       
   982 #if defined(Q_OS_SYMBIAN)
       
   983     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
   984 #endif
       
   985 
       
   986     QProcess proc;
       
   987     connect(&proc, SIGNAL(readyRead()), this, SLOT(exitLoopSlot()));
       
   988     QSignalSpy spy(&proc, SIGNAL(readyRead()));
       
   989 
       
   990 #ifdef Q_OS_MAC
       
   991     proc.start("testProcessEcho/testProcessEcho.app");
       
   992 #else
       
   993     proc.start("testProcessEcho/testProcessEcho");
       
   994 #endif
       
   995 
       
   996     QCOMPARE(spy.count(), 0);
       
   997 
       
   998     proc.write("A");
       
   999 
       
  1000     QTestEventLoop::instance().enterLoop(5);
       
  1001     if (QTestEventLoop::instance().timeout())
       
  1002         QFAIL("Operation timed out");
       
  1003 
       
  1004     QCOMPARE(spy.count(), 1);
       
  1005 
       
  1006     QTestEventLoop::instance().enterLoop(1);
       
  1007     QVERIFY(QTestEventLoop::instance().timeout());
       
  1008     QVERIFY(!proc.waitForReadyRead(250));
       
  1009 
       
  1010     QObject::disconnect(&proc, SIGNAL(readyRead()), 0, 0);
       
  1011     proc.write("B");
       
  1012     QVERIFY(proc.waitForReadyRead(5000));
       
  1013 
       
  1014     proc.write("", 1);
       
  1015     QVERIFY(proc.waitForFinished(5000));
       
  1016 }
       
  1017 
       
  1018 //-----------------------------------------------------------------------------
       
  1019 void tst_QProcess::hardExit()
       
  1020 {
       
  1021 #if defined(Q_OS_SYMBIAN)
       
  1022     QSKIP("Killing started processes is not supported on Qt/Symbian due platform security", SkipAll);
       
  1023 #endif
       
  1024     QProcess proc;
       
  1025 
       
  1026 #if defined(Q_OS_MAC)
       
  1027     proc.start("testProcessEcho/testProcessEcho.app");
       
  1028 #elif defined(Q_OS_WINCE)
       
  1029     proc.start("testSoftExit/testSoftExit");
       
  1030 #else
       
  1031     proc.start("testProcessEcho/testProcessEcho");
       
  1032 #endif
       
  1033 
       
  1034 #ifndef Q_OS_WINCE
       
  1035     QVERIFY(proc.waitForStarted(5000));
       
  1036 #else
       
  1037     QVERIFY(proc.waitForStarted(10000));
       
  1038 #endif
       
  1039 
       
  1040     proc.kill();
       
  1041 
       
  1042     QVERIFY(proc.waitForFinished(5000));
       
  1043     QCOMPARE(int(proc.state()), int(QProcess::NotRunning));
       
  1044     QCOMPARE(int(proc.error()), int(QProcess::Crashed));
       
  1045 }
       
  1046 
       
  1047 //-----------------------------------------------------------------------------
       
  1048 void tst_QProcess::softExit()
       
  1049 {
       
  1050 #if defined(Q_OS_SYMBIAN)
       
  1051     QSKIP("Terminating started processes is not supported on Qt/Symbian due platform security", SkipAll);
       
  1052 #endif
       
  1053     QProcess proc;
       
  1054 
       
  1055     proc.start("testSoftExit/testSoftExit");
       
  1056 
       
  1057     QVERIFY(proc.waitForStarted(10000));
       
  1058 #if !defined(Q_OS_WINCE)
       
  1059     QVERIFY(proc.waitForReadyRead(10000));
       
  1060 #endif
       
  1061 
       
  1062     proc.terminate();
       
  1063 
       
  1064     QVERIFY(proc.waitForFinished(10000));
       
  1065     QCOMPARE(int(proc.state()), int(QProcess::NotRunning));
       
  1066     QCOMPARE(int(proc.error()), int(QProcess::UnknownError));
       
  1067 }
       
  1068 
       
  1069 class SoftExitProcess : public QProcess
       
  1070 {
       
  1071     Q_OBJECT
       
  1072 public:
       
  1073     bool waitedForFinished;
       
  1074 
       
  1075     SoftExitProcess(int n) : waitedForFinished(false), n(n), killing(false)
       
  1076     {
       
  1077         connect(this, SIGNAL(finished(int, QProcess::ExitStatus)),
       
  1078                 this, SLOT(finishedSlot(int, QProcess::ExitStatus)));
       
  1079 
       
  1080         switch (n) {
       
  1081         case 0:
       
  1082             setReadChannelMode(QProcess::MergedChannels);
       
  1083             connect(this, SIGNAL(readyRead()), this, SLOT(terminateSlot()));
       
  1084             break;
       
  1085         case 1:
       
  1086             connect(this, SIGNAL(readyReadStandardOutput()),
       
  1087                     this, SLOT(terminateSlot()));
       
  1088             break;
       
  1089         case 2:
       
  1090             connect(this, SIGNAL(readyReadStandardError()),
       
  1091                     this, SLOT(terminateSlot()));
       
  1092             break;
       
  1093         case 3:
       
  1094             connect(this, SIGNAL(started()),
       
  1095                     this, SLOT(terminateSlot()));
       
  1096             break;
       
  1097         case 4:
       
  1098         default:
       
  1099             connect(this, SIGNAL(stateChanged(QProcess::ProcessState)),
       
  1100                     this, SLOT(terminateSlot()));
       
  1101             break;
       
  1102         }
       
  1103     }
       
  1104 
       
  1105 public slots:
       
  1106     void terminateSlot()
       
  1107     {
       
  1108         if (killing || (n == 4 && state() != Running)) {
       
  1109             // Don't try to kill the process before it is running - that can
       
  1110             // be hazardous, as the actual child process might not be running
       
  1111             // yet. Also, don't kill it "recursively".
       
  1112             return;
       
  1113         }
       
  1114         killing = true;
       
  1115         readAll();
       
  1116         terminate();
       
  1117         if ((waitedForFinished = waitForFinished(5000)) == false) {
       
  1118             kill();
       
  1119             if (state() != NotRunning)
       
  1120                 waitedForFinished = waitForFinished(5000);
       
  1121         }
       
  1122     }
       
  1123 
       
  1124     void finishedSlot(int, QProcess::ExitStatus)
       
  1125     {
       
  1126         waitedForFinished = true;
       
  1127     }
       
  1128 
       
  1129 private:
       
  1130     int n;
       
  1131     bool killing;
       
  1132 };
       
  1133 
       
  1134 //-----------------------------------------------------------------------------
       
  1135 void tst_QProcess::softExitInSlots_data()
       
  1136 {
       
  1137     QTest::addColumn<QString>("appName");
       
  1138 
       
  1139 #ifdef Q_OS_MAC
       
  1140     QTest::newRow("gui app") << "testGuiProcess/testGuiProcess.app";
       
  1141 #else
       
  1142     QTest::newRow("gui app") << "testGuiProcess/testGuiProcess";
       
  1143 #endif
       
  1144 #ifdef Q_OS_MAC
       
  1145     QTest::newRow("console app") << "testProcessEcho2/testProcessEcho2.app";
       
  1146 #else
       
  1147     QTest::newRow("console app") << "testProcessEcho2/testProcessEcho2";
       
  1148 #endif
       
  1149 }
       
  1150 
       
  1151 //-----------------------------------------------------------------------------
       
  1152 void tst_QProcess::softExitInSlots()
       
  1153 {
       
  1154 #ifdef Q_OS_WINCE
       
  1155     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1156 #endif
       
  1157 #if defined(Q_OS_SYMBIAN)
       
  1158     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  1159 #endif
       
  1160 
       
  1161     QFETCH(QString, appName);
       
  1162 
       
  1163     for (int i = 0; i < 5; ++i) {
       
  1164         SoftExitProcess proc(i);
       
  1165         proc.start(appName);
       
  1166         proc.write("OLEBOLE", 8); // include the \0
       
  1167         QTestEventLoop::instance().enterLoop(10);
       
  1168         QCOMPARE(proc.state(), QProcess::NotRunning);
       
  1169         QVERIFY(proc.waitedForFinished);
       
  1170     }
       
  1171 }
       
  1172 
       
  1173 //-----------------------------------------------------------------------------
       
  1174 void tst_QProcess::mergedChannels()
       
  1175 {
       
  1176 #ifdef Q_OS_WINCE
       
  1177     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1178 #endif
       
  1179 #if defined(Q_OS_SYMBIAN)
       
  1180     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  1181 #endif
       
  1182 
       
  1183     QProcess process;
       
  1184     process.setReadChannelMode(QProcess::MergedChannels);
       
  1185     QCOMPARE(process.readChannelMode(), QProcess::MergedChannels);
       
  1186 
       
  1187 #ifdef Q_OS_MAC
       
  1188     process.start("testProcessEcho2/testProcessEcho2.app");
       
  1189 #else
       
  1190     process.start("testProcessEcho2/testProcessEcho2");
       
  1191 #endif
       
  1192 
       
  1193     QVERIFY(process.waitForStarted(5000));
       
  1194 
       
  1195     for (int i = 0; i < 100; ++i) {
       
  1196         QCOMPARE(process.write("abc"), qlonglong(3));
       
  1197         while (process.bytesAvailable() < 6)
       
  1198             QVERIFY(process.waitForReadyRead(5000));
       
  1199         QCOMPARE(process.readAll(), QByteArray("aabbcc"));
       
  1200     }
       
  1201 
       
  1202     process.closeWriteChannel();
       
  1203     QVERIFY(process.waitForFinished(5000));
       
  1204 }
       
  1205 
       
  1206 //-----------------------------------------------------------------------------
       
  1207 void tst_QProcess::forwardedChannels()
       
  1208 {
       
  1209 #ifdef Q_OS_WINCE
       
  1210     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1211 #endif
       
  1212 #if defined(Q_OS_SYMBIAN)
       
  1213     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  1214 #endif
       
  1215 
       
  1216     QProcess process;
       
  1217     process.setReadChannelMode(QProcess::ForwardedChannels);
       
  1218     QCOMPARE(process.readChannelMode(), QProcess::ForwardedChannels);
       
  1219 
       
  1220 #ifdef Q_OS_MAC
       
  1221     process.start("testProcessEcho2/testProcessEcho2.app");
       
  1222 #else
       
  1223     process.start("testProcessEcho2/testProcessEcho2");
       
  1224 #endif
       
  1225 
       
  1226     QVERIFY(process.waitForStarted(5000));
       
  1227     QCOMPARE(process.write("forwarded\n"), qlonglong(10));
       
  1228     QVERIFY(!process.waitForReadyRead(250));
       
  1229     QCOMPARE(process.bytesAvailable(), qlonglong(0));
       
  1230 
       
  1231     process.closeWriteChannel();
       
  1232     QVERIFY(process.waitForFinished(5000));
       
  1233 }
       
  1234 
       
  1235 
       
  1236 //-----------------------------------------------------------------------------
       
  1237 void tst_QProcess::atEnd()
       
  1238 {
       
  1239 #ifdef Q_OS_WINCE
       
  1240     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1241 #endif
       
  1242 #if defined(Q_OS_SYMBIAN)
       
  1243     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  1244 #endif
       
  1245 
       
  1246     QProcess process;
       
  1247 
       
  1248 #ifdef Q_OS_MAC
       
  1249     process.start("testProcessEcho/testProcessEcho.app");
       
  1250 #else
       
  1251     process.start("testProcessEcho/testProcessEcho");
       
  1252 #endif
       
  1253     process.write("abcdefgh\n");
       
  1254 
       
  1255     while (process.bytesAvailable() < 8)
       
  1256         QVERIFY(process.waitForReadyRead(5000));
       
  1257 
       
  1258     QTextStream stream(&process);
       
  1259     QVERIFY(!stream.atEnd());
       
  1260     QString tmp = stream.readLine();
       
  1261     QVERIFY(stream.atEnd());
       
  1262     QCOMPARE(tmp, QString::fromLatin1("abcdefgh"));
       
  1263 
       
  1264     process.write("", 1);
       
  1265     QVERIFY(process.waitForFinished(5000));
       
  1266 }
       
  1267 
       
  1268 class TestThread : public QThread
       
  1269 {
       
  1270     Q_OBJECT
       
  1271 public:
       
  1272     inline int code()
       
  1273     {
       
  1274         return exitCode;
       
  1275     }
       
  1276 
       
  1277 #if defined(Q_OS_SYMBIAN)
       
  1278     int serial;
       
  1279 #endif
       
  1280 
       
  1281 protected:
       
  1282     inline void run()
       
  1283     {
       
  1284         exitCode = 90210;
       
  1285 
       
  1286         QProcess process;
       
  1287         connect(&process, SIGNAL(finished(int)), this, SLOT(catchExitCode(int)),
       
  1288                 Qt::DirectConnection);
       
  1289 
       
  1290 #ifdef Q_OS_MAC
       
  1291         process.start("testProcessEcho/testProcessEcho.app");
       
  1292 #elif defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86)
       
  1293     // WINSCW builds in Symbian do not allow multiple processes to load Qt libraries,
       
  1294     // so use just a simple process instead of testDetached.
       
  1295     process.start("testProcessNormal");
       
  1296 #elif defined(Q_OS_SYMBIAN)
       
  1297         // testDetached used because it does something, but doesn't take too long.
       
  1298         QFile infoFile(QString("c:\\logs\\detinfo%1").arg(serial));
       
  1299         QStringList args;
       
  1300         args << infoFile.fileName();
       
  1301         process.start("testDetached", args);
       
  1302 #else
       
  1303         process.start("testProcessEcho/testProcessEcho");
       
  1304 #endif
       
  1305 
       
  1306 #if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
       
  1307         QCOMPARE(process.write("abc\0", 4), qint64(4));
       
  1308 #endif
       
  1309         exitCode = exec();
       
  1310     }
       
  1311 
       
  1312 protected slots:
       
  1313     inline void catchExitCode(int exitCode)
       
  1314     {
       
  1315         this->exitCode = exitCode;
       
  1316         exit(exitCode);
       
  1317     }
       
  1318 
       
  1319 private:
       
  1320     int exitCode;
       
  1321 };
       
  1322 
       
  1323 //-----------------------------------------------------------------------------
       
  1324 void tst_QProcess::processInAThread()
       
  1325 {
       
  1326     for (int i = 0; i < 10; ++i) {
       
  1327         TestThread thread;
       
  1328         thread.start();
       
  1329         QVERIFY(thread.wait(10000));
       
  1330         QCOMPARE(thread.code(), 0);
       
  1331     }
       
  1332 }
       
  1333 
       
  1334 //-----------------------------------------------------------------------------
       
  1335 void tst_QProcess::processesInMultipleThreads()
       
  1336 {
       
  1337 #if defined(Q_OS_SYMBIAN)
       
  1338     int serialCounter = 0;
       
  1339 #endif
       
  1340 
       
  1341     for (int i = 0; i < 10; ++i) {
       
  1342         TestThread thread1;
       
  1343         TestThread thread2;
       
  1344         TestThread thread3;
       
  1345 
       
  1346 #if defined(Q_OS_SYMBIAN)
       
  1347         thread1.serial = serialCounter++;
       
  1348         thread2.serial = serialCounter++;
       
  1349         thread3.serial = serialCounter++;
       
  1350 #endif
       
  1351         thread1.start();
       
  1352         thread2.start();
       
  1353         thread3.start();
       
  1354 
       
  1355         QVERIFY(thread2.wait(10000));
       
  1356         QVERIFY(thread3.wait(10000));
       
  1357         QVERIFY(thread1.wait(10000));
       
  1358 
       
  1359         QCOMPARE(thread1.code(), 0);
       
  1360         QCOMPARE(thread2.code(), 0);
       
  1361         QCOMPARE(thread3.code(), 0);
       
  1362     }
       
  1363 }
       
  1364 
       
  1365 //-----------------------------------------------------------------------------
       
  1366 void tst_QProcess::waitForFinishedWithTimeout()
       
  1367 {
       
  1368 #ifdef Q_OS_WINCE
       
  1369     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1370 #endif
       
  1371 
       
  1372     process = new QProcess(this);
       
  1373 
       
  1374 #ifdef Q_OS_MAC
       
  1375     process->start("testProcessEcho/testProcessEcho.app");
       
  1376 #elif defined(Q_OS_SYMBIAN)
       
  1377     process->start("testProcessOutput");
       
  1378 #else
       
  1379     process->start("testProcessEcho/testProcessEcho");
       
  1380 #endif
       
  1381 
       
  1382 #if defined(Q_OS_SYMBIAN)
       
  1383     QVERIFY(process->waitForStarted(50));
       
  1384     QVERIFY(!process->waitForFinished(1));
       
  1385 #else
       
  1386     QVERIFY(process->waitForStarted(5000));
       
  1387     QVERIFY(!process->waitForFinished(1));
       
  1388 
       
  1389     process->write("", 1);
       
  1390 #endif
       
  1391 
       
  1392     QVERIFY(process->waitForFinished());
       
  1393 
       
  1394     delete process;
       
  1395     process = 0;
       
  1396 }
       
  1397 
       
  1398 //-----------------------------------------------------------------------------
       
  1399 void tst_QProcess::waitForReadyReadInAReadyReadSlot()
       
  1400 {
       
  1401 #ifdef Q_OS_WINCE
       
  1402     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1403 #endif
       
  1404 #if defined(Q_OS_SYMBIAN)
       
  1405     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  1406 #endif
       
  1407 
       
  1408     process = new QProcess(this);
       
  1409     connect(process, SIGNAL(readyRead()), this, SLOT(waitForReadyReadInAReadyReadSlotSlot()));
       
  1410     connect(process, SIGNAL(finished(int)), this, SLOT(exitLoopSlot()));
       
  1411     bytesAvailable = 0;
       
  1412 
       
  1413 #ifdef Q_OS_MAC
       
  1414     process->start("testProcessEcho/testProcessEcho.app");
       
  1415 #else
       
  1416     process->start("testProcessEcho/testProcessEcho");
       
  1417 #endif
       
  1418     QVERIFY(process->waitForStarted(5000));
       
  1419 
       
  1420     QSignalSpy spy(process, SIGNAL(readyRead()));
       
  1421     process->write("foo");
       
  1422     QTestEventLoop::instance().enterLoop(30);
       
  1423     QVERIFY(!QTestEventLoop::instance().timeout());
       
  1424 
       
  1425     QCOMPARE(spy.count(), 1);
       
  1426 
       
  1427     process->disconnect();
       
  1428     QVERIFY(process->waitForFinished(5000));
       
  1429     QVERIFY(process->bytesAvailable() > bytesAvailable);
       
  1430     delete process;
       
  1431     process = 0;
       
  1432 }
       
  1433 
       
  1434 //-----------------------------------------------------------------------------
       
  1435 void tst_QProcess::waitForReadyReadInAReadyReadSlotSlot()
       
  1436 {
       
  1437 #ifdef Q_OS_WINCE
       
  1438     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1439 #endif
       
  1440 #if defined(Q_OS_SYMBIAN)
       
  1441     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  1442 #endif
       
  1443 
       
  1444     bytesAvailable = process->bytesAvailable();
       
  1445     process->write("bar", 4);
       
  1446     QVERIFY(process->waitForReadyRead(5000));
       
  1447     QTestEventLoop::instance().exitLoop();
       
  1448 }
       
  1449 
       
  1450 //-----------------------------------------------------------------------------
       
  1451 void tst_QProcess::waitForBytesWrittenInABytesWrittenSlot()
       
  1452 {
       
  1453 #ifdef Q_OS_WINCE
       
  1454     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1455 #endif
       
  1456 #if defined(Q_OS_SYMBIAN)
       
  1457     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  1458 #endif
       
  1459 
       
  1460     process = new QProcess(this);
       
  1461     connect(process, SIGNAL(bytesWritten(qint64)), this, SLOT(waitForBytesWrittenInABytesWrittenSlotSlot()));
       
  1462     bytesAvailable = 0;
       
  1463 
       
  1464 #ifdef Q_OS_MAC
       
  1465     process->start("testProcessEcho/testProcessEcho.app");
       
  1466 #else
       
  1467     process->start("testProcessEcho/testProcessEcho");
       
  1468 #endif
       
  1469     QVERIFY(process->waitForStarted(5000));
       
  1470 
       
  1471     qRegisterMetaType<qint64>("qint64");
       
  1472     QSignalSpy spy(process, SIGNAL(bytesWritten(qint64)));
       
  1473     process->write("f");
       
  1474     QTestEventLoop::instance().enterLoop(30);
       
  1475     QVERIFY(!QTestEventLoop::instance().timeout());
       
  1476 
       
  1477     QCOMPARE(spy.count(), 1);
       
  1478     process->write("", 1);
       
  1479     process->disconnect();
       
  1480     QVERIFY(process->waitForFinished());
       
  1481     delete process;
       
  1482     process = 0;
       
  1483 }
       
  1484 
       
  1485 //-----------------------------------------------------------------------------
       
  1486 void tst_QProcess::waitForBytesWrittenInABytesWrittenSlotSlot()
       
  1487 {
       
  1488 #ifdef Q_OS_WINCE
       
  1489     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1490 #endif
       
  1491 #if defined(Q_OS_SYMBIAN)
       
  1492     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  1493 #endif
       
  1494 
       
  1495     process->write("b");
       
  1496     QVERIFY(process->waitForBytesWritten(5000));
       
  1497     QTestEventLoop::instance().exitLoop();
       
  1498 }
       
  1499 
       
  1500 //-----------------------------------------------------------------------------
       
  1501 void tst_QProcess::spaceArgsTest_data()
       
  1502 {
       
  1503     QTest::addColumn<QStringList>("args");
       
  1504     QTest::addColumn<QString>("stringArgs");
       
  1505 
       
  1506     // arg1 | arg2
       
  1507     QTest::newRow("arg1 arg2") << (QStringList() << QString::fromLatin1("arg1") << QString::fromLatin1("arg2"))
       
  1508                                << QString::fromLatin1("arg1 arg2");
       
  1509     // "arg1" | ar "g2
       
  1510     QTest::newRow("\"\"\"\"arg1\"\"\"\" \"ar \"\"\"g2\"") << (QStringList() << QString::fromLatin1("\"arg1\"") << QString::fromLatin1("ar \"g2"))
       
  1511                                                           << QString::fromLatin1("\"\"\"\"arg1\"\"\"\" \"ar \"\"\"g2\"");
       
  1512     // ar g1 | a rg 2
       
  1513     QTest::newRow("\"ar g1\" \"a rg 2\"") << (QStringList() << QString::fromLatin1("ar g1") << QString::fromLatin1("a rg 2"))
       
  1514                                           << QString::fromLatin1("\"ar g1\" \"a rg 2\"");
       
  1515     // -lar g1 | -l"ar g2"
       
  1516     QTest::newRow("\"-lar g1\" \"-l\"\"\"ar g2\"\"\"\"") << (QStringList() << QString::fromLatin1("-lar g1") << QString::fromLatin1("-l\"ar g2\""))
       
  1517                                                          << QString::fromLatin1("\"-lar g1\" \"-l\"\"\"ar g2\"\"\"\"");
       
  1518     // ar"g1
       
  1519     QTest::newRow("ar\"\"\"\"g1") << (QStringList() << QString::fromLatin1("ar\"g1"))
       
  1520                                   << QString::fromLatin1("ar\"\"\"\"g1");
       
  1521     // ar/g1
       
  1522     QTest::newRow("ar\\g1") << (QStringList() << QString::fromLatin1("ar\\g1"))
       
  1523                             << QString::fromLatin1("ar\\g1");
       
  1524     // ar\g"1
       
  1525     QTest::newRow("ar\\g\"\"\"\"1") << (QStringList() << QString::fromLatin1("ar\\g\"1"))
       
  1526                                     << QString::fromLatin1("ar\\g\"\"\"\"1");
       
  1527     // arg\"1
       
  1528     QTest::newRow("arg\\\"\"\"1") << (QStringList() << QString::fromLatin1("arg\\\"1"))
       
  1529                                   << QString::fromLatin1("arg\\\"\"\"1");
       
  1530     // """"
       
  1531     QTest::newRow("\"\"\"\"\"\"\"\"\"\"\"\"") << (QStringList() << QString::fromLatin1("\"\"\"\""))
       
  1532                                               << QString::fromLatin1("\"\"\"\"\"\"\"\"\"\"\"\"");
       
  1533     // """" | "" ""
       
  1534     QTest::newRow("\"\"\"\"\"\"\"\"\"\"\"\" \"\"\"\"\"\"\" \"\"\"\"\"\"\"") << (QStringList() << QString::fromLatin1("\"\"\"\"") << QString::fromLatin1("\"\" \"\""))
       
  1535                                                                             << QString::fromLatin1("\"\"\"\"\"\"\"\"\"\"\"\" \"\"\"\"\"\"\" \"\"\"\"\"\"\"");
       
  1536     // ""  ""
       
  1537     QTest::newRow("\"\"\"\"\"\"\" \"\" \"\"\"\"\"\"\" (bogus double quotes)") << (QStringList() << QString::fromLatin1("\"\"  \"\""))
       
  1538                                                                               << QString::fromLatin1("\"\"\"\"\"\"\" \"\" \"\"\"\"\"\"\"");
       
  1539     // ""  ""
       
  1540     QTest::newRow(" \"\"\"\"\"\"\" \"\" \"\"\"\"\"\"\"   (bogus double quotes)") << (QStringList() << QString::fromLatin1("\"\"  \"\""))
       
  1541                                                                                  << QString::fromLatin1(" \"\"\"\"\"\"\" \"\" \"\"\"\"\"\"\"   ");
       
  1542 }
       
  1543 
       
  1544 //-----------------------------------------------------------------------------
       
  1545 void tst_QProcess::spaceArgsTest()
       
  1546 {
       
  1547     QFETCH(QStringList, args);
       
  1548     QFETCH(QString, stringArgs);
       
  1549 
       
  1550     QStringList programs;
       
  1551     programs << QString::fromLatin1("testProcessSpacesArgs/nospace")
       
  1552 #if defined(Q_OS_SYMBIAN)
       
  1553     ; // Symbian toolchain doesn't like exes with spaces in the name
       
  1554 #else
       
  1555              << QString::fromLatin1("testProcessSpacesArgs/one space")
       
  1556              << QString::fromLatin1("testProcessSpacesArgs/two space s");
       
  1557 #endif
       
  1558 
       
  1559     process = new QProcess(this);
       
  1560 
       
  1561     for (int i = 0; i < programs.size(); ++i) {
       
  1562         QString program = programs.at(i);
       
  1563         process->start(program, args);
       
  1564 
       
  1565 #if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
       
  1566         QVERIFY(process->waitForStarted(5000));
       
  1567         QVERIFY(process->waitForFinished(5000));
       
  1568 #else
       
  1569         QVERIFY(process->waitForStarted(10000));
       
  1570         QVERIFY(process->waitForFinished(10000));
       
  1571 #endif
       
  1572 
       
  1573 #if defined(Q_OS_SYMBIAN)
       
  1574         // Symbian test outputs to a file, so check that
       
  1575         FILE* file = fopen("c:\\logs\\qprocess_args_test.txt","r");
       
  1576         char buf[256];
       
  1577         fgets(buf, 256, file);
       
  1578         fclose(file);
       
  1579         QStringList actual = QString::fromLatin1(buf).split("|");
       
  1580 #elif !defined(Q_OS_WINCE)
       
  1581         QStringList actual = QString::fromLatin1(process->readAll()).split("|");
       
  1582 #endif
       
  1583 #if !defined(Q_OS_WINCE)
       
  1584         QVERIFY(!actual.isEmpty());
       
  1585         // not interested in the program name, it might be different.
       
  1586         actual.removeFirst();
       
  1587 
       
  1588         QCOMPARE(actual, args);
       
  1589 #endif
       
  1590 
       
  1591         if (program.contains(" "))
       
  1592             program = "\"" + program + "\"";
       
  1593 
       
  1594         if (!stringArgs.isEmpty())
       
  1595             program += QString::fromLatin1(" ") + stringArgs;
       
  1596 
       
  1597         process->start(program);
       
  1598 
       
  1599         QVERIFY(process->waitForStarted(5000));
       
  1600         QVERIFY(process->waitForFinished(5000));
       
  1601 
       
  1602 #if defined(Q_OS_SYMBIAN)
       
  1603         // Symbian test outputs to a file, so check that
       
  1604         file = fopen("c:\\logs\\qprocess_args_test.txt","r");
       
  1605         fgets(buf, 256, file);
       
  1606         fclose(file);
       
  1607         actual = QString::fromLatin1(buf).split("|");
       
  1608 #elif !defined(Q_OS_WINCE)
       
  1609         actual = QString::fromLatin1(process->readAll()).split("|");
       
  1610 #endif
       
  1611 #if !defined(Q_OS_WINCE)
       
  1612         QVERIFY(!actual.isEmpty());
       
  1613         // not interested in the program name, it might be different.
       
  1614         actual.removeFirst();
       
  1615 
       
  1616         QCOMPARE(actual, args);
       
  1617 #endif
       
  1618     }
       
  1619 
       
  1620     delete process;
       
  1621     process = 0;
       
  1622 }
       
  1623 
       
  1624 //-----------------------------------------------------------------------------
       
  1625 void tst_QProcess::exitCodeTest()
       
  1626 {
       
  1627 #if defined(Q_OS_SYMBIAN)
       
  1628     // Kernel will run out of process handles on some hw, as there is some
       
  1629     // delay before they are recycled, so limit the amount of processes.
       
  1630     for (int i = 0; i < 50; ++i) {
       
  1631 #else
       
  1632     for (int i = 0; i < 255; ++i) {
       
  1633 #endif
       
  1634         QProcess process;
       
  1635         process.start("testExitCodes/testExitCodes " + QString::number(i));
       
  1636         QVERIFY(process.waitForFinished(5000));
       
  1637         QCOMPARE(process.exitCode(), i);
       
  1638         QCOMPARE(process.error(), QProcess::UnknownError);
       
  1639     }
       
  1640 }
       
  1641 
       
  1642 //-----------------------------------------------------------------------------
       
  1643 void tst_QProcess::failToStart()
       
  1644 {
       
  1645     qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
       
  1646     qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
       
  1647     qRegisterMetaType<QProcess::ProcessState>("QProcess::ProcessState");
       
  1648 
       
  1649     QProcess process;
       
  1650     QSignalSpy stateSpy(&process, SIGNAL(stateChanged(QProcess::ProcessState)));
       
  1651     QSignalSpy errorSpy(&process, SIGNAL(error(QProcess::ProcessError)));
       
  1652     QSignalSpy finishedSpy(&process, SIGNAL(finished(int)));
       
  1653     QSignalSpy finishedSpy2(&process, SIGNAL(finished(int, QProcess::ExitStatus)));
       
  1654 
       
  1655 // Mac OS X and HP-UX have a really low defualt process limit (~100), so spawning
       
  1656 // to many processes here will cause test failures later on.
       
  1657 #if defined Q_OS_HPUX
       
  1658    const int attempts = 15;
       
  1659 #elif defined Q_OS_MAC
       
  1660    const int attempts = 15;
       
  1661 #else
       
  1662    const int attempts = 50;
       
  1663 #endif
       
  1664 
       
  1665     for (int j = 0; j < 8; ++j) {
       
  1666         for (int i = 0; i < attempts; ++i) {
       
  1667             QCOMPARE(errorSpy.count(), j * attempts + i);
       
  1668             process.start("/blurp");
       
  1669 
       
  1670             switch (j) {
       
  1671             case 0:
       
  1672             case 1:
       
  1673                 QVERIFY(!process.waitForStarted());
       
  1674                 break;
       
  1675             case 2:
       
  1676             case 3:
       
  1677                 QVERIFY(!process.waitForFinished());
       
  1678                 break;
       
  1679             case 4:
       
  1680             case 5:
       
  1681                 QVERIFY(!process.waitForReadyRead());
       
  1682                 break;
       
  1683             case 6:
       
  1684             case 7:
       
  1685             default:
       
  1686                 QVERIFY(!process.waitForBytesWritten());
       
  1687                 break;
       
  1688             }
       
  1689 
       
  1690             QCOMPARE(process.error(), QProcess::FailedToStart);
       
  1691             QCOMPARE(errorSpy.count(), j * attempts + i + 1);
       
  1692             QCOMPARE(finishedSpy.count(), 0);
       
  1693             QCOMPARE(finishedSpy2.count(), 0);
       
  1694 
       
  1695             int it = j * attempts + i + 1;
       
  1696 
       
  1697             QCOMPARE(stateSpy.count(), it * 2);
       
  1698             QCOMPARE(qVariantValue<QProcess::ProcessState>(stateSpy.at(it * 2 - 2).at(0)), QProcess::Starting);
       
  1699             QCOMPARE(qVariantValue<QProcess::ProcessState>(stateSpy.at(it * 2 - 1).at(0)), QProcess::NotRunning);
       
  1700         }
       
  1701     }
       
  1702 }
       
  1703 
       
  1704 //-----------------------------------------------------------------------------
       
  1705 void tst_QProcess::failToStartWithWait()
       
  1706 {
       
  1707     qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
       
  1708     qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
       
  1709 
       
  1710     QProcess process;
       
  1711     QEventLoop loop;
       
  1712     QSignalSpy errorSpy(&process, SIGNAL(error(QProcess::ProcessError)));
       
  1713     QSignalSpy finishedSpy(&process, SIGNAL(finished(int)));
       
  1714     QSignalSpy finishedSpy2(&process, SIGNAL(finished(int, QProcess::ExitStatus)));
       
  1715 
       
  1716     for (int i = 0; i < 50; ++i) {
       
  1717         process.start("/blurp", QStringList() << "-v" << "-debug");
       
  1718         process.waitForStarted();
       
  1719 
       
  1720         QCOMPARE(process.error(), QProcess::FailedToStart);
       
  1721         QCOMPARE(errorSpy.count(), i + 1);
       
  1722         QCOMPARE(finishedSpy.count(), 0);
       
  1723         QCOMPARE(finishedSpy2.count(), 0);
       
  1724     }
       
  1725 }
       
  1726 
       
  1727 //-----------------------------------------------------------------------------
       
  1728 void tst_QProcess::failToStartWithEventLoop()
       
  1729 {
       
  1730     qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
       
  1731     qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
       
  1732 
       
  1733     QProcess process;
       
  1734     QEventLoop loop;
       
  1735     QSignalSpy errorSpy(&process, SIGNAL(error(QProcess::ProcessError)));
       
  1736     QSignalSpy finishedSpy(&process, SIGNAL(finished(int)));
       
  1737     QSignalSpy finishedSpy2(&process, SIGNAL(finished(int, QProcess::ExitStatus)));
       
  1738 
       
  1739     // The error signal may be emitted before start() returns
       
  1740     connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit()), Qt::QueuedConnection);
       
  1741 
       
  1742 
       
  1743     for (int i = 0; i < 50; ++i) {
       
  1744         process.start("/blurp", QStringList() << "-v" << "-debug");
       
  1745 
       
  1746         loop.exec();
       
  1747 
       
  1748         QCOMPARE(process.error(), QProcess::FailedToStart);
       
  1749         QCOMPARE(errorSpy.count(), i + 1);
       
  1750         QCOMPARE(finishedSpy.count(), 0);
       
  1751         QCOMPARE(finishedSpy2.count(), 0);
       
  1752     }
       
  1753 }
       
  1754 
       
  1755 //-----------------------------------------------------------------------------
       
  1756 void tst_QProcess::removeFileWhileProcessIsRunning()
       
  1757 {
       
  1758 #ifdef Q_OS_WINCE
       
  1759     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1760 #endif
       
  1761 #if defined(Q_OS_SYMBIAN)
       
  1762     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  1763 #endif
       
  1764 
       
  1765     QFile file("removeFile.txt");
       
  1766     QVERIFY(file.open(QFile::WriteOnly));
       
  1767 
       
  1768     QProcess process;
       
  1769 #ifdef Q_OS_MAC
       
  1770     process.start("testProcessEcho/testProcessEcho.app");
       
  1771 #else
       
  1772     process.start("testProcessEcho/testProcessEcho");
       
  1773 #endif
       
  1774 
       
  1775     QVERIFY(process.waitForStarted(5000));
       
  1776 
       
  1777     QVERIFY(file.remove());
       
  1778 
       
  1779     process.write("", 1);
       
  1780     QVERIFY(process.waitForFinished(5000));
       
  1781 }
       
  1782 
       
  1783 //-----------------------------------------------------------------------------
       
  1784 void tst_QProcess::setEnvironment_data()
       
  1785 {
       
  1786     QTest::addColumn<QString>("name");
       
  1787     QTest::addColumn<QString>("value");
       
  1788 
       
  1789     QTest::newRow("setting-empty") << "tst_QProcess" << "";
       
  1790     QTest::newRow("setting") << "tst_QProcess" << "value";
       
  1791 
       
  1792 #ifdef Q_OS_WIN
       
  1793     QTest::newRow("unsetting") << "PROMPT" << QString();
       
  1794     QTest::newRow("overriding") << "PROMPT" << "value";
       
  1795 #else
       
  1796     QTest::newRow("unsetting") << "PATH" << QString();
       
  1797     QTest::newRow("overriding") << "PATH" << "value";
       
  1798 #endif
       
  1799 }
       
  1800 
       
  1801 void tst_QProcess::setEnvironment()
       
  1802 {
       
  1803 #if defined (Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
       
  1804     QSKIP("OS doesn't support environment variables", SkipAll);
       
  1805 #endif
       
  1806 
       
  1807     // make sure our environment variables are correct
       
  1808     QVERIFY(qgetenv("tst_QProcess").isEmpty());
       
  1809     QVERIFY(!qgetenv("PATH").isEmpty());
       
  1810 #ifdef Q_OS_WIN
       
  1811     QVERIFY(!qgetenv("PROMPT").isEmpty());
       
  1812 #endif
       
  1813 
       
  1814     QFETCH(QString, name);
       
  1815     QFETCH(QString, value);
       
  1816     QString executable = QDir::currentPath() + "/testProcessEnvironment/testProcessEnvironment";
       
  1817 
       
  1818     {
       
  1819         QProcess process;
       
  1820         QStringList environment = QProcess::systemEnvironment();
       
  1821         if (value.isNull()) {
       
  1822             int pos;
       
  1823             QRegExp rx(name + "=.*");
       
  1824 #ifdef Q_OS_WIN
       
  1825             rx.setCaseSensitivity(Qt::CaseInsensitive);
       
  1826 #endif
       
  1827             while ((pos = environment.indexOf(rx)) != -1)
       
  1828                 environment.removeAt(pos);
       
  1829         } else {
       
  1830             environment.append(name + '=' + value);
       
  1831         }
       
  1832         process.setEnvironment(environment);
       
  1833         process.start(executable, QStringList() << name);
       
  1834 
       
  1835         QVERIFY(process.waitForFinished());
       
  1836         if (value.isNull())
       
  1837             QCOMPARE(process.exitCode(), 1);
       
  1838         else if (!value.isEmpty())
       
  1839             QCOMPARE(process.exitCode(), 0);
       
  1840 
       
  1841         QCOMPARE(process.readAll(), value.toLocal8Bit());
       
  1842     }
       
  1843 
       
  1844     // re-do the test but set the environment twice, to make sure
       
  1845     // that the latter addition overrides
       
  1846     // this test doesn't make sense in unsetting
       
  1847     if (!value.isNull()) {
       
  1848         QProcess process;
       
  1849         QStringList environment = QProcess::systemEnvironment();
       
  1850         environment.prepend(name + "=This is not the right value");
       
  1851         environment.append(name + '=' + value);
       
  1852         process.setEnvironment(environment);
       
  1853         process.start(executable, QStringList() << name);
       
  1854 
       
  1855         QVERIFY(process.waitForFinished());
       
  1856         if (!value.isEmpty())
       
  1857             QCOMPARE(process.exitCode(), 0);
       
  1858 
       
  1859         QCOMPARE(process.readAll(), value.toLocal8Bit());
       
  1860     }
       
  1861 }
       
  1862 
       
  1863 //-----------------------------------------------------------------------------
       
  1864 void tst_QProcess::setProcessEnvironment_data()
       
  1865 {
       
  1866     setEnvironment_data();
       
  1867 }
       
  1868 
       
  1869 void tst_QProcess::setProcessEnvironment()
       
  1870 {
       
  1871 #if defined (Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
       
  1872     QSKIP("OS doesn't support environment variables", SkipAll);
       
  1873 #endif
       
  1874 
       
  1875     // make sure our environment variables are correct
       
  1876     QVERIFY(qgetenv("tst_QProcess").isEmpty());
       
  1877     QVERIFY(!qgetenv("PATH").isEmpty());
       
  1878 #ifdef Q_OS_WIN
       
  1879     QVERIFY(!qgetenv("PROMPT").isEmpty());
       
  1880 #endif
       
  1881 
       
  1882     QFETCH(QString, name);
       
  1883     QFETCH(QString, value);
       
  1884     QString executable = QDir::currentPath() + "/testProcessEnvironment/testProcessEnvironment";
       
  1885 
       
  1886     {
       
  1887         QProcess process;
       
  1888         QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
       
  1889         if (value.isNull())
       
  1890             environment.remove(name);
       
  1891         else
       
  1892             environment.insert(name, value);
       
  1893         process.setProcessEnvironment(environment);
       
  1894         process.start(executable, QStringList() << name);
       
  1895 
       
  1896         QVERIFY(process.waitForFinished());
       
  1897         if (value.isNull())
       
  1898             QCOMPARE(process.exitCode(), 1);
       
  1899         else if (!value.isEmpty())
       
  1900             QCOMPARE(process.exitCode(), 0);
       
  1901 
       
  1902         QCOMPARE(process.readAll(), value.toLocal8Bit());
       
  1903     }
       
  1904 }
       
  1905 //-----------------------------------------------------------------------------
       
  1906 void tst_QProcess::systemEnvironment()
       
  1907 {
       
  1908 #if defined (Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
       
  1909     // there is no concept of system variables on Windows CE as there is no console
       
  1910     QVERIFY(QProcess::systemEnvironment().isEmpty());
       
  1911     QVERIFY(QProcessEnvironment::systemEnvironment().isEmpty());
       
  1912 #else
       
  1913     QVERIFY(!QProcess::systemEnvironment().isEmpty());
       
  1914     QVERIFY(!QProcessEnvironment::systemEnvironment().isEmpty());
       
  1915 
       
  1916     QVERIFY(QProcessEnvironment::systemEnvironment().contains("PATH"));
       
  1917     QVERIFY(!QProcess::systemEnvironment().filter(QRegExp("^PATH=", Qt::CaseInsensitive)).isEmpty());
       
  1918 #endif
       
  1919 }
       
  1920 
       
  1921 //-----------------------------------------------------------------------------
       
  1922 void tst_QProcess::spaceInName()
       
  1923 {
       
  1924 #ifdef Q_OS_WINCE
       
  1925     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1926 #endif
       
  1927 #if defined(Q_OS_SYMBIAN)
       
  1928     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  1929 #endif
       
  1930     QProcess process;
       
  1931     process.start("test Space In Name/testSpaceInName", QStringList());
       
  1932     QVERIFY(process.waitForStarted());
       
  1933     process.write("", 1);
       
  1934     QVERIFY(process.waitForFinished());
       
  1935 }
       
  1936 
       
  1937 //-----------------------------------------------------------------------------
       
  1938 void tst_QProcess::lockupsInStartDetached()
       
  1939 {
       
  1940 #if !defined(Q_OS_SYMBIAN)
       
  1941     // What exactly is this call supposed to achieve anyway?
       
  1942     QHostInfo::lookupHost(QString("something.invalid"), 0, 0);
       
  1943 #endif
       
  1944     QProcess::execute("yjhbrty");
       
  1945     QProcess::startDetached("yjhbrty");
       
  1946 }
       
  1947 
       
  1948 //-----------------------------------------------------------------------------
       
  1949 void tst_QProcess::atEnd2()
       
  1950 {
       
  1951 #ifdef Q_OS_WINCE
       
  1952     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  1953 #endif
       
  1954 #if defined(Q_OS_SYMBIAN)
       
  1955     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  1956 #endif
       
  1957 
       
  1958     QProcess process;
       
  1959 
       
  1960 #ifdef Q_OS_MAC
       
  1961     process.start("testProcessEcho/testProcessEcho.app");
       
  1962 #else
       
  1963     process.start("testProcessEcho/testProcessEcho");
       
  1964 #endif
       
  1965     process.write("Foo\nBar\nBaz\nBodukon\nHadukan\nTorwukan\nend\n");
       
  1966     process.putChar('\0');
       
  1967     QVERIFY(process.waitForFinished());
       
  1968     QList<QByteArray> lines;
       
  1969     while (!process.atEnd()) {
       
  1970         lines << process.readLine();
       
  1971     }
       
  1972     QCOMPARE(lines.size(), 7);
       
  1973 }
       
  1974 
       
  1975 //-----------------------------------------------------------------------------
       
  1976 void tst_QProcess::waitForReadyReadForNonexistantProcess()
       
  1977 {
       
  1978     // This comes from task 108968
       
  1979     // Start a program that doesn't exist, process events and then try to waitForReadyRead
       
  1980     qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
       
  1981     qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
       
  1982 
       
  1983     QProcess process;
       
  1984     QSignalSpy errorSpy(&process, SIGNAL(error(QProcess::ProcessError)));
       
  1985     QSignalSpy finishedSpy1(&process, SIGNAL(finished(int)));
       
  1986     QSignalSpy finishedSpy2(&process, SIGNAL(finished(int, QProcess::ExitStatus)));
       
  1987     QVERIFY(!process.waitForReadyRead()); // used to crash
       
  1988     process.start("doesntexist");
       
  1989     QVERIFY(!process.waitForReadyRead());
       
  1990     QCOMPARE(errorSpy.count(), 1);
       
  1991     QCOMPARE(errorSpy.at(0).at(0).toInt(), 0);
       
  1992     QCOMPARE(finishedSpy1.count(), 0);
       
  1993     QCOMPARE(finishedSpy2.count(), 0);
       
  1994 }
       
  1995 
       
  1996 //-----------------------------------------------------------------------------
       
  1997 void tst_QProcess::setStandardInputFile()
       
  1998 {
       
  1999 #ifdef Q_OS_WINCE
       
  2000     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  2001 #endif
       
  2002 #if defined(Q_OS_SYMBIAN)
       
  2003     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  2004 #endif
       
  2005 
       
  2006     static const char data[] = "A bunch\1of\2data\3\4\5\6\7...";
       
  2007     QProcess process;
       
  2008     QFile file("data");
       
  2009 
       
  2010     QVERIFY(file.open(QIODevice::WriteOnly));
       
  2011     file.write(data, sizeof data);
       
  2012     file.close();
       
  2013 
       
  2014     process.setStandardInputFile("data");
       
  2015 #ifdef Q_OS_MAC
       
  2016     process.start("testProcessEcho/testProcessEcho.app");
       
  2017 #else
       
  2018     process.start("testProcessEcho/testProcessEcho");
       
  2019 #endif
       
  2020 
       
  2021     QPROCESS_VERIFY(process, waitForFinished());
       
  2022 	QByteArray all = process.readAll();
       
  2023     QCOMPARE(all.size(), int(sizeof data) - 1); // testProcessEcho drops the ending \0
       
  2024     QVERIFY(all == data);
       
  2025 }
       
  2026 
       
  2027 //-----------------------------------------------------------------------------
       
  2028 void tst_QProcess::setStandardOutputFile_data()
       
  2029 {
       
  2030     QTest::addColumn<int>("channelToTest");
       
  2031     QTest::addColumn<int>("_channelMode");
       
  2032     QTest::addColumn<bool>("append");
       
  2033 
       
  2034     QTest::newRow("stdout-truncate") << int(QProcess::StandardOutput)
       
  2035                                      << int(QProcess::SeparateChannels)
       
  2036                                      << false;
       
  2037     QTest::newRow("stdout-append") << int(QProcess::StandardOutput)
       
  2038                                    << int(QProcess::SeparateChannels)
       
  2039                                    << true;
       
  2040 
       
  2041     QTest::newRow("stderr-truncate") << int(QProcess::StandardError)
       
  2042                                      << int(QProcess::SeparateChannels)
       
  2043                                      << false;
       
  2044     QTest::newRow("stderr-append") << int(QProcess::StandardError)
       
  2045                                    << int(QProcess::SeparateChannels)
       
  2046                                    << true;
       
  2047 
       
  2048     QTest::newRow("merged-truncate") << int(QProcess::StandardOutput)
       
  2049                                      << int(QProcess::MergedChannels)
       
  2050                                      << false;
       
  2051     QTest::newRow("merged-append") << int(QProcess::StandardOutput)
       
  2052                                    << int(QProcess::MergedChannels)
       
  2053                                    << true;
       
  2054 }
       
  2055 
       
  2056 void tst_QProcess::setStandardOutputFile()
       
  2057 {
       
  2058 #ifdef Q_OS_WINCE
       
  2059     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  2060 #endif
       
  2061 #if defined(Q_OS_SYMBIAN)
       
  2062     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  2063 #endif
       
  2064 
       
  2065     static const char data[] = "Original data. ";
       
  2066     static const char testdata[] = "Test data.";
       
  2067 
       
  2068     QFETCH(int, channelToTest);
       
  2069     QFETCH(int, _channelMode);
       
  2070     QFETCH(bool, append);
       
  2071 
       
  2072     QProcess::ProcessChannelMode channelMode = QProcess::ProcessChannelMode(_channelMode);
       
  2073     QIODevice::OpenMode mode = append ? QIODevice::Append : QIODevice::Truncate;
       
  2074 
       
  2075     // create the destination file with data
       
  2076     QFile file("data");
       
  2077     QVERIFY(file.open(QIODevice::WriteOnly));
       
  2078     file.write(data, sizeof data - 1);
       
  2079     file.close();
       
  2080 
       
  2081     // run the process
       
  2082     QProcess process;
       
  2083     process.setReadChannelMode(channelMode);
       
  2084     if (channelToTest == QProcess::StandardOutput)
       
  2085         process.setStandardOutputFile("data", mode);
       
  2086     else
       
  2087         process.setStandardErrorFile("data", mode);
       
  2088 
       
  2089 #ifdef Q_OS_MAC
       
  2090     process.start("testProcessEcho2/testProcessEcho2.app");
       
  2091 #else
       
  2092     process.start("testProcessEcho2/testProcessEcho2");
       
  2093 #endif
       
  2094     process.write(testdata, sizeof testdata);
       
  2095     QPROCESS_VERIFY(process,waitForFinished());
       
  2096 
       
  2097     // open the file again and verify the data
       
  2098     QVERIFY(file.open(QIODevice::ReadOnly));
       
  2099     QByteArray all = file.readAll();
       
  2100     file.close();
       
  2101 
       
  2102     int expectedsize = sizeof testdata - 1;
       
  2103     if (mode == QIODevice::Append) {
       
  2104         QVERIFY(all.startsWith(data));
       
  2105         expectedsize += sizeof data - 1;
       
  2106     }
       
  2107     if (channelMode == QProcess::MergedChannels) {
       
  2108         expectedsize += sizeof testdata - 1;
       
  2109     } else {
       
  2110         QVERIFY(all.endsWith(testdata));
       
  2111     }
       
  2112 
       
  2113     QCOMPARE(all.size(), expectedsize);
       
  2114 }
       
  2115 
       
  2116 //-----------------------------------------------------------------------------
       
  2117 void tst_QProcess::setStandardOutputProcess_data()
       
  2118 {
       
  2119     QTest::addColumn<bool>("merged");
       
  2120     QTest::newRow("separate") << false;
       
  2121     QTest::newRow("merged") << true;
       
  2122 }
       
  2123 
       
  2124 void tst_QProcess::setStandardOutputProcess()
       
  2125 {
       
  2126 #ifdef Q_OS_WINCE
       
  2127     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  2128 #endif
       
  2129 #if defined(Q_OS_SYMBIAN)
       
  2130     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  2131 #endif
       
  2132 
       
  2133     QProcess source;
       
  2134     QProcess sink;
       
  2135 
       
  2136     QFETCH(bool, merged);
       
  2137     source.setReadChannelMode(merged ? QProcess::MergedChannels : QProcess::SeparateChannels);
       
  2138     source.setStandardOutputProcess(&sink);
       
  2139 
       
  2140 #ifdef Q_OS_MAC
       
  2141     source.start("testProcessEcho2/testProcessEcho2.app");
       
  2142     sink.start("testProcessEcho2/testProcessEcho2.app");
       
  2143 #else
       
  2144     source.start("testProcessEcho2/testProcessEcho2");
       
  2145     sink.start("testProcessEcho2/testProcessEcho2");
       
  2146 #endif
       
  2147 
       
  2148     QByteArray data("Hello, World");
       
  2149     source.write(data);
       
  2150     source.closeWriteChannel();
       
  2151     QPROCESS_VERIFY(source, waitForFinished());
       
  2152     QPROCESS_VERIFY(sink, waitForFinished());
       
  2153     QByteArray all = sink.readAll();
       
  2154 
       
  2155     if (!merged)
       
  2156         QCOMPARE(all, data);
       
  2157     else
       
  2158         QCOMPARE(all, QByteArray("HHeelllloo,,  WWoorrlldd"));
       
  2159 }
       
  2160 
       
  2161 //-----------------------------------------------------------------------------
       
  2162 void tst_QProcess::fileWriterProcess()
       
  2163 {
       
  2164 #ifdef Q_OS_WINCE
       
  2165     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  2166 #endif
       
  2167 #if defined(Q_OS_SYMBIAN)
       
  2168     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  2169 #endif
       
  2170 
       
  2171     QString stdinStr;
       
  2172     for (int i = 0; i < 5000; ++i)
       
  2173         stdinStr += QString::fromLatin1("%1 -- testing testing 1 2 3\n").arg(i);
       
  2174 
       
  2175     QTime stopWatch;
       
  2176     stopWatch.start();
       
  2177     do {
       
  2178         QFile::remove("fileWriterProcess.txt");
       
  2179         QProcess process;
       
  2180         process.start("fileWriterProcess/fileWriterProcess",
       
  2181                       QIODevice::ReadWrite | QIODevice::Text);
       
  2182         process.write(stdinStr.toLatin1());
       
  2183         process.closeWriteChannel();
       
  2184         while (process.bytesToWrite()) {
       
  2185             QVERIFY(stopWatch.elapsed() < 3500);
       
  2186             QVERIFY(process.waitForBytesWritten(2000));
       
  2187         }
       
  2188         QVERIFY(process.waitForFinished());
       
  2189         QCOMPARE(QFile("fileWriterProcess.txt").size(), qint64(stdinStr.size()));
       
  2190     } while (stopWatch.elapsed() < 3000);
       
  2191 }
       
  2192 
       
  2193 //-----------------------------------------------------------------------------
       
  2194 void tst_QProcess::detachedWorkingDirectoryAndPid()
       
  2195 {
       
  2196 #if defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86)
       
  2197     // WINSCW builds in Symbian do not allow multiple processes to load Qt libraries,
       
  2198     // so this test must be skipped.
       
  2199     QSKIP("Multiple processes loading Qt are not allowed in Qt/Symbian emulator.", SkipAll);
       
  2200 #endif
       
  2201     qint64 pid;
       
  2202 
       
  2203 #ifdef Q_OS_WINCE
       
  2204     QTest::qSleep(1000);
       
  2205 #endif
       
  2206 
       
  2207 #if defined(Q_OS_SYMBIAN)
       
  2208     // Symbian has no working directory support, so use logs dir as a shared directory
       
  2209     QFile infoFile(QLatin1String("c:\\logs\\detachedinfo.txt"));
       
  2210 #else
       
  2211     QFile infoFile(QDir::currentPath() + QLatin1String("/detachedinfo.txt"));
       
  2212 #endif
       
  2213     infoFile.remove();
       
  2214 
       
  2215     QString workingDir = QDir::currentPath() + "/testDetached";
       
  2216 
       
  2217 #ifndef Q_OS_SYMBIAN
       
  2218     QVERIFY(QFile::exists(workingDir));
       
  2219 #endif
       
  2220 
       
  2221     QStringList args;
       
  2222     args << infoFile.fileName();
       
  2223     QVERIFY(QProcess::startDetached(QDir::currentPath() + QLatin1String("/testDetached/testDetached"), args, workingDir, &pid));
       
  2224 
       
  2225     QFileInfo fi(infoFile);
       
  2226     fi.setCaching(false);
       
  2227     while (fi.size() == 0) {
       
  2228         QTest::qSleep(100);
       
  2229     }
       
  2230 
       
  2231     QVERIFY(infoFile.open(QIODevice::ReadOnly | QIODevice::Text));
       
  2232     QString actualWorkingDir = QString::fromUtf8(infoFile.readLine());
       
  2233     actualWorkingDir.chop(1); // strip off newline
       
  2234     QByteArray processIdString = infoFile.readLine();
       
  2235     processIdString.chop(1);
       
  2236     infoFile.close();
       
  2237     infoFile.remove();
       
  2238 
       
  2239     bool ok = false;
       
  2240     qint64 actualPid = processIdString.toLongLong(&ok);
       
  2241     QVERIFY(ok);
       
  2242 
       
  2243 #if defined(Q_OS_SYMBIAN)
       
  2244     QEXPECT_FAIL("", "Working directory is not supported on Qt/symbian", Continue);
       
  2245 #endif
       
  2246     QCOMPARE(actualWorkingDir, workingDir);
       
  2247     QCOMPARE(actualPid, pid);
       
  2248 }
       
  2249 
       
  2250 //-----------------------------------------------------------------------------
       
  2251 void tst_QProcess::switchReadChannels()
       
  2252 {
       
  2253 #ifdef Q_OS_WINCE
       
  2254     QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll);
       
  2255 #endif
       
  2256 #if defined(Q_OS_SYMBIAN)
       
  2257     QSKIP("Reading and writing to a process is not supported on Qt/Symbian", SkipAll);
       
  2258 #endif
       
  2259     const char data[] = "ABCD";
       
  2260 
       
  2261     QProcess process;
       
  2262 
       
  2263 #ifdef Q_OS_MAC
       
  2264     process.start("testProcessEcho2/testProcessEcho2.app");
       
  2265 #else
       
  2266     process.start("testProcessEcho2/testProcessEcho2");
       
  2267 #endif
       
  2268     process.write(data);
       
  2269     process.closeWriteChannel();
       
  2270     QVERIFY(process.waitForFinished(5000));
       
  2271 
       
  2272     for (int i = 0; i < 4; ++i) {
       
  2273         process.setReadChannel(QProcess::StandardOutput);
       
  2274         QCOMPARE(process.read(1), QByteArray(&data[i], 1));
       
  2275         process.setReadChannel(QProcess::StandardError);
       
  2276         QCOMPARE(process.read(1), QByteArray(&data[i], 1));
       
  2277     }
       
  2278 
       
  2279     process.ungetChar('D');
       
  2280     process.setReadChannel(QProcess::StandardOutput);
       
  2281     process.ungetChar('D');
       
  2282     process.setReadChannel(QProcess::StandardError);
       
  2283     QCOMPARE(process.read(1), QByteArray("D"));
       
  2284     process.setReadChannel(QProcess::StandardOutput);
       
  2285     QCOMPARE(process.read(1), QByteArray("D"));
       
  2286 }
       
  2287 
       
  2288 //-----------------------------------------------------------------------------
       
  2289 void tst_QProcess::setWorkingDirectory()
       
  2290 {
       
  2291 #ifdef Q_OS_WINCE
       
  2292     QSKIP("Windows CE does not support working directory logic", SkipAll);
       
  2293 #endif
       
  2294 #if defined(Q_OS_SYMBIAN)
       
  2295     QSKIP("Symbian does not support working directory logic", SkipAll);
       
  2296 #endif
       
  2297     process = new QProcess;
       
  2298     process->setWorkingDirectory("test");
       
  2299 #ifdef Q_OS_MAC
       
  2300     process->start("testSetWorkingDirectory/testSetWorkingDirectory.app");
       
  2301 #else
       
  2302     process->start("testSetWorkingDirectory/testSetWorkingDirectory");
       
  2303 #endif
       
  2304 #ifndef Q_OS_WIN
       
  2305     QSKIP("setWorkingDirectory will chdir before starting the process on unices", SkipAll);
       
  2306 #endif
       
  2307     QVERIFY(process->waitForFinished());
       
  2308 
       
  2309     QByteArray workingDir = process->readAllStandardOutput();
       
  2310     QCOMPARE(QDir("test").canonicalPath(), QDir(workingDir.constData()).canonicalPath());
       
  2311 
       
  2312     delete process;
       
  2313     process = 0;
       
  2314 }
       
  2315 
       
  2316 //-----------------------------------------------------------------------------
       
  2317 void tst_QProcess::startFinishStartFinish()
       
  2318 {
       
  2319     QProcess process;
       
  2320 
       
  2321     for (int i = 0; i < 3; ++i) {
       
  2322         QCOMPARE(process.state(), QProcess::NotRunning);
       
  2323 
       
  2324 #ifdef Q_OS_MAC
       
  2325         process.start("testProcessOutput/testProcessOutput.app");
       
  2326 #else
       
  2327         process.start("testProcessOutput/testProcessOutput");
       
  2328 #endif
       
  2329 #if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
       
  2330         QVERIFY(process.waitForReadyRead(10000));
       
  2331         QCOMPARE(QString::fromLatin1(process.readLine().trimmed()),
       
  2332                  QString("0 -this is a number"));
       
  2333 #endif
       
  2334         if (process.state() != QProcess::NotRunning)
       
  2335             QVERIFY(process.waitForFinished(10000));
       
  2336 #if defined(Q_OS_SYMBIAN)
       
  2337         // Symbian test outputs to a file, so check that
       
  2338         FILE* file = fopen("c:\\logs\\qprocess_output_test.txt","r");
       
  2339         char buf[30];
       
  2340         fgets(buf, 30, file);
       
  2341         QCOMPARE(QString::fromLatin1(buf),
       
  2342                  QString("0 -this is a number\n"));
       
  2343         fclose(file);
       
  2344 #endif
       
  2345     }
       
  2346 }
       
  2347 
       
  2348 //-----------------------------------------------------------------------------
       
  2349 void tst_QProcess::invalidProgramString_data()
       
  2350 {
       
  2351     QTest::addColumn<QString>("programString");
       
  2352     QTest::newRow("null string") << QString();
       
  2353     QTest::newRow("empty string") << QString("");
       
  2354     QTest::newRow("only blank string") << QString("  ");
       
  2355 }
       
  2356 
       
  2357 void tst_QProcess::invalidProgramString()
       
  2358 {
       
  2359     QFETCH(QString, programString);
       
  2360     QProcess process;
       
  2361 
       
  2362     qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
       
  2363     QSignalSpy spy(&process, SIGNAL(error(QProcess::ProcessError)));
       
  2364 
       
  2365     process.start(programString);
       
  2366     QCOMPARE(process.error(), QProcess::FailedToStart);
       
  2367     QCOMPARE(spy.count(), 1);
       
  2368 
       
  2369     QVERIFY(!QProcess::startDetached(programString));
       
  2370 }
       
  2371 
       
  2372 QTEST_MAIN(tst_QProcess)
       
  2373 #include "tst_qprocess.moc"
       
  2374 #endif
       
  2375