From 7ad55ca65f42351e231f31f7a9253ae6eaf1ebb3 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 30 May 2017 13:53:33 +0200 Subject: Support standard channel redirection in QProcess::startDetached [ChangeLog][QtCore][QProcess] Added support for standard channel redirection using setStandard{Input|Output|Error}File to QProcess::startDetached. Task-number: QTBUG-2058 Task-number: QTBUG-37656 Change-Id: Iafb9bd7899f752d0305e3410ad4dcb7ef598dc79 Reviewed-by: Thiago Macieira --- .../auto/corelib/io/qprocess/testDetached/main.cpp | 87 ++++++++++++++++++---- tests/auto/corelib/io/qprocess/tst_qprocess.cpp | 36 ++++++++- 2 files changed, 106 insertions(+), 17 deletions(-) (limited to 'tests/auto/corelib') diff --git a/tests/auto/corelib/io/qprocess/testDetached/main.cpp b/tests/auto/corelib/io/qprocess/testDetached/main.cpp index c970ce5aa0..c10e32d584 100644 --- a/tests/auto/corelib/io/qprocess/testDetached/main.cpp +++ b/tests/auto/corelib/io/qprocess/testDetached/main.cpp @@ -40,23 +40,8 @@ #include #endif -int main(int argc, char **argv) +static void writeStuff(QFile &f) { - QCoreApplication app(argc, argv); - - QStringList args = app.arguments(); - if (args.count() != 2) { - fprintf(stderr, "Usage: testDetached filename.txt\n"); - return 128; - } - - QFile f(args.at(1)); - if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { - fprintf(stderr, "Cannot open %s for writing: %s\n", - qPrintable(f.fileName()), qPrintable(f.errorString())); - return 1; - } - f.write(QDir::currentPath().toUtf8()); f.putChar('\n'); #if defined(Q_OS_UNIX) @@ -67,7 +52,77 @@ int main(int argc, char **argv) f.putChar('\n'); f.write(qgetenv("tst_QProcess")); f.putChar('\n'); +} + +struct Args +{ + int exitCode = 0; + QByteArray errorMessage; + QString fileName; + FILE *channel = nullptr; + QByteArray channelName; +}; + +static Args parseArguments(const QStringList &args) +{ + Args result; + if (args.count() < 2) { + result.exitCode = 128; + result.errorMessage = "Usage: testDetached [--out-channel={stdout|stderr}] filename.txt\n"; + return result; + } + for (const QString &arg : args) { + if (arg.startsWith("--")) { + if (!arg.startsWith("--out-channel=")) { + result.exitCode = 2; + result.errorMessage = "Unknown argument " + arg.toLocal8Bit(); + return result; + } + result.channelName = arg.mid(14).toLocal8Bit(); + if (result.channelName == "stdout") { + result.channel = stdout; + } else if (result.channelName == "stderr") { + result.channel = stderr; + } else { + result.exitCode = 3; + result.errorMessage = "Unknown channel " + result.channelName; + return result; + } + } else { + result.fileName = arg; + } + } + return result; +} + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + const Args args = parseArguments(app.arguments()); + if (args.exitCode) { + fprintf(stderr, "testDetached: %s\n", args.errorMessage.constData()); + return args.exitCode; + } + + if (args.channel) { + QFile channel; + if (!channel.open(args.channel, QIODevice::WriteOnly | QIODevice::Text)) { + fprintf(stderr, "Cannot open channel %s for writing: %s\n", + qPrintable(args.channelName), qPrintable(channel.errorString())); + return 4; + } + writeStuff(channel); + } + + QFile f(args.fileName); + if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { + fprintf(stderr, "Cannot open %s for writing: %s\n", + qPrintable(f.fileName()), qPrintable(f.errorString())); + return 1; + } + writeStuff(f); f.close(); return 0; diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index f8268f5991..6b1516600f 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -126,6 +126,7 @@ private slots: void systemEnvironment(); void lockupsInStartDetached(); void waitForReadyReadForNonexistantProcess(); + void detachedProcessParameters_data(); void detachedProcessParameters(); void startFinishStartFinish(); void invalidProgramString_data(); @@ -2030,13 +2031,25 @@ void tst_QProcess::fileWriterProcess() } while (stopWatch.elapsed() < 3000); } +void tst_QProcess::detachedProcessParameters_data() +{ + QTest::addColumn("outChannel"); + QTest::newRow("none") << QString(); + QTest::newRow("stdout") << QString("stdout"); + QTest::newRow("stderr") << QString("stderr"); +} + void tst_QProcess::detachedProcessParameters() { + QFETCH(QString, outChannel); qint64 pid; QFile infoFile(m_temporaryDir.path() + QLatin1String("/detachedinfo.txt")); if (infoFile.exists()) QVERIFY(infoFile.remove()); + QFile channelFile(m_temporaryDir.path() + QLatin1String("detachedinfo2.txt")); + if (channelFile.exists()) + QVERIFY(channelFile.remove()); QString workingDir = QDir::currentPath() + "/testDetached"; @@ -2054,7 +2067,15 @@ void tst_QProcess::detachedProcessParameters() process.setCreateProcessArgumentsModifier( [&modifierCalls] (QProcess::CreateProcessArguments *) { modifierCalls++; }); #endif - process.setArguments(QStringList(infoFile.fileName())); + QStringList args(infoFile.fileName()); + if (!outChannel.isEmpty()) { + args << QStringLiteral("--out-channel=") + outChannel; + if (outChannel == "stdout") + process.setStandardOutputFile(channelFile.fileName()); + else if (outChannel == "stderr") + process.setStandardErrorFile(channelFile.fileName()); + } + process.setArguments(args); process.setWorkingDirectory(workingDir); process.setProcessEnvironment(environment); QVERIFY(process.startDetached(&pid)); @@ -2071,9 +2092,22 @@ void tst_QProcess::detachedProcessParameters() QString actualWorkingDir = QString::fromUtf8(infoFile.readLine()).trimmed(); QByteArray processIdString = infoFile.readLine().trimmed(); QByteArray actualEnvVarValue = infoFile.readLine().trimmed(); + QByteArray infoFileContent; + if (!outChannel.isEmpty()) { + infoFile.seek(0); + infoFileContent = infoFile.readAll(); + } infoFile.close(); infoFile.remove(); + if (!outChannel.isEmpty()) { + QVERIFY(channelFile.open(QIODevice::ReadOnly | QIODevice::Text)); + QByteArray channelContent = channelFile.readAll(); + channelFile.close(); + channelFile.remove(); + QCOMPARE(channelContent, infoFileContent); + } + bool ok = false; qint64 actualPid = processIdString.toLongLong(&ok); QVERIFY(ok); -- cgit v1.2.3