From b28f90711491c329cf7e439f193aaf4d53e9f922 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 10 Jun 2022 10:18:34 +0200 Subject: [PATCH] AutoTest: Use QtcProcess for test runner Change-Id: I29b15a08a260aaf8d2c4071d5ea71d49902d8ef6 Reviewed-by: David Schulz --- .../autotest/boost/boosttestconfiguration.cpp | 2 +- .../autotest/boost/boosttestconfiguration.h | 2 +- .../autotest/boost/boosttestoutputreader.cpp | 8 ++-- .../autotest/boost/boosttestoutputreader.h | 4 +- .../autotest/catch/catchconfiguration.cpp | 3 +- .../autotest/catch/catchconfiguration.h | 2 +- .../autotest/catch/catchoutputreader.cpp | 3 +- .../autotest/catch/catchoutputreader.h | 2 +- .../autotest/ctest/ctestconfiguration.cpp | 2 +- .../autotest/ctest/ctestconfiguration.h | 2 +- .../autotest/ctest/ctestoutputreader.cpp | 2 +- .../autotest/ctest/ctestoutputreader.h | 4 +- .../autotest/gtest/gtestconfiguration.cpp | 2 +- .../autotest/gtest/gtestconfiguration.h | 2 +- .../autotest/gtest/gtestoutputreader.cpp | 10 +++-- .../autotest/gtest/gtestoutputreader.h | 2 +- .../autotest/qtest/qttestconfiguration.cpp | 2 +- .../autotest/qtest/qttestconfiguration.h | 2 +- .../autotest/qtest/qttestoutputreader.cpp | 2 +- .../autotest/qtest/qttestoutputreader.h | 2 +- .../autotest/quick/quicktestconfiguration.cpp | 2 +- .../autotest/quick/quicktestconfiguration.h | 2 +- src/plugins/autotest/testconfiguration.h | 6 +-- src/plugins/autotest/testoutputreader.cpp | 20 ++++----- src/plugins/autotest/testoutputreader.h | 7 ++-- src/plugins/autotest/testrunconfiguration.h | 2 +- src/plugins/autotest/testrunner.cpp | 41 +++++++++++-------- src/plugins/autotest/testrunner.h | 6 ++- 28 files changed, 79 insertions(+), 67 deletions(-) diff --git a/src/plugins/autotest/boost/boosttestconfiguration.cpp b/src/plugins/autotest/boost/boosttestconfiguration.cpp index 5e65962a52e..556228bd653 100644 --- a/src/plugins/autotest/boost/boosttestconfiguration.cpp +++ b/src/plugins/autotest/boost/boosttestconfiguration.cpp @@ -39,7 +39,7 @@ namespace Autotest { namespace Internal { TestOutputReader *BoostTestConfiguration::outputReader(const QFutureInterface &fi, - QProcess *app) const + Utils::QtcProcess *app) const { auto settings = static_cast(framework()->testSettings()); return new BoostTestOutputReader(fi, app, buildDirectory(), projectFile(), diff --git a/src/plugins/autotest/boost/boosttestconfiguration.h b/src/plugins/autotest/boost/boosttestconfiguration.h index 2259eca5137..d3d4b851df4 100644 --- a/src/plugins/autotest/boost/boosttestconfiguration.h +++ b/src/plugins/autotest/boost/boosttestconfiguration.h @@ -36,7 +36,7 @@ public: explicit BoostTestConfiguration(ITestFramework *framework) : DebuggableTestConfiguration(framework) {} TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const override; + Utils::QtcProcess *app) const override; QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override; Utils::Environment filteredEnvironment(const Utils::Environment &original) const override; }; diff --git a/src/plugins/autotest/boost/boosttestoutputreader.cpp b/src/plugins/autotest/boost/boosttestoutputreader.cpp index 5036a683ff3..a9668fc8e80 100644 --- a/src/plugins/autotest/boost/boosttestoutputreader.cpp +++ b/src/plugins/autotest/boost/boosttestoutputreader.cpp @@ -29,6 +29,7 @@ #include "boosttesttreeitem.h" #include +#include #include #include @@ -41,7 +42,7 @@ namespace Internal { static Q_LOGGING_CATEGORY(orLog, "qtc.autotest.boost.outputreader", QtWarningMsg) BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile, LogLevel log, ReportLevel report) @@ -51,7 +52,7 @@ BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface::of(&QProcess::finished), + connect(m_testApplication, &Utils::QtcProcess::finished, this, &BoostTestOutputReader::onFinished); } } @@ -405,7 +406,8 @@ TestResultPtr BoostTestOutputReader::createDefaultResult() const return TestResultPtr(result); } -void BoostTestOutputReader::onFinished(int exitCode, QProcess::ExitStatus /*exitState*/) { +void BoostTestOutputReader::onFinished() { + int exitCode = m_testApplication->exitCode(); if (m_reportLevel == ReportLevel::No && m_testCaseCount != -1) { int reportedFailsAndSkips = m_summary[ResultType::Fail] + m_summary[ResultType::Skip]; m_summary.insert(ResultType::Pass, m_testCaseCount - reportedFailsAndSkips); diff --git a/src/plugins/autotest/boost/boosttestoutputreader.h b/src/plugins/autotest/boost/boosttestoutputreader.h index 56527fa6271..b5cab378a7c 100644 --- a/src/plugins/autotest/boost/boosttestoutputreader.h +++ b/src/plugins/autotest/boost/boosttestoutputreader.h @@ -39,7 +39,7 @@ class BoostTestOutputReader : public TestOutputReader Q_OBJECT public: BoostTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile, LogLevel log, ReportLevel report); protected: void processOutputLine(const QByteArray &outputLine) override; @@ -47,7 +47,7 @@ protected: TestResultPtr createDefaultResult() const override; private: - void onFinished(int exitCode, QProcess::ExitStatus /*exitState*/); + void onFinished(); void sendCompleteInformation(); void handleMessageMatch(const QRegularExpressionMatch &match); void reportNoOutputFinish(const QString &description, ResultType type); diff --git a/src/plugins/autotest/catch/catchconfiguration.cpp b/src/plugins/autotest/catch/catchconfiguration.cpp index bb1353ff4a9..4a3436d476b 100644 --- a/src/plugins/autotest/catch/catchconfiguration.cpp +++ b/src/plugins/autotest/catch/catchconfiguration.cpp @@ -35,7 +35,8 @@ namespace Autotest { namespace Internal { -TestOutputReader *CatchConfiguration::outputReader(const QFutureInterface &fi, QProcess *app) const +TestOutputReader *CatchConfiguration::outputReader(const QFutureInterface &fi, + Utils::QtcProcess *app) const { return new CatchOutputReader(fi, app, buildDirectory(), projectFile()); } diff --git a/src/plugins/autotest/catch/catchconfiguration.h b/src/plugins/autotest/catch/catchconfiguration.h index 2a198558098..ef3549514b5 100644 --- a/src/plugins/autotest/catch/catchconfiguration.h +++ b/src/plugins/autotest/catch/catchconfiguration.h @@ -34,7 +34,7 @@ class CatchConfiguration : public DebuggableTestConfiguration public: CatchConfiguration(ITestFramework *framework) : DebuggableTestConfiguration(framework) {} TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const override; + Utils::QtcProcess *app) const override; QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override; Utils::Environment filteredEnvironment(const Utils::Environment &original) const override; }; diff --git a/src/plugins/autotest/catch/catchoutputreader.cpp b/src/plugins/autotest/catch/catchoutputreader.cpp index f7ae4d3bc8f..f788aea017c 100644 --- a/src/plugins/autotest/catch/catchoutputreader.cpp +++ b/src/plugins/autotest/catch/catchoutputreader.cpp @@ -49,7 +49,8 @@ namespace CatchXml { } CatchOutputReader::CatchOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory, + Utils::QtcProcess *testApplication, + const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile) : TestOutputReader (futureInterface, testApplication, buildDirectory) , m_projectFile(projectFile) diff --git a/src/plugins/autotest/catch/catchoutputreader.h b/src/plugins/autotest/catch/catchoutputreader.h index 70158309617..86c3acbb034 100644 --- a/src/plugins/autotest/catch/catchoutputreader.h +++ b/src/plugins/autotest/catch/catchoutputreader.h @@ -39,7 +39,7 @@ class CatchOutputReader : public TestOutputReader public: CatchOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile); protected: diff --git a/src/plugins/autotest/ctest/ctestconfiguration.cpp b/src/plugins/autotest/ctest/ctestconfiguration.cpp index de2a94061e1..2a1d18389fb 100644 --- a/src/plugins/autotest/ctest/ctestconfiguration.cpp +++ b/src/plugins/autotest/ctest/ctestconfiguration.cpp @@ -36,7 +36,7 @@ CTestConfiguration::CTestConfiguration(ITestBase *testBase) } TestOutputReader *CTestConfiguration::outputReader(const QFutureInterface &fi, - QProcess *app) const + Utils::QtcProcess *app) const { return new CTestOutputReader(fi, app, workingDirectory()); } diff --git a/src/plugins/autotest/ctest/ctestconfiguration.h b/src/plugins/autotest/ctest/ctestconfiguration.h index 77f7904ab31..3c62c7ea843 100644 --- a/src/plugins/autotest/ctest/ctestconfiguration.h +++ b/src/plugins/autotest/ctest/ctestconfiguration.h @@ -36,7 +36,7 @@ public: explicit CTestConfiguration(ITestBase *testBase); TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const final; + Utils::QtcProcess *app) const final; }; } // namespace Internal diff --git a/src/plugins/autotest/ctest/ctestoutputreader.cpp b/src/plugins/autotest/ctest/ctestoutputreader.cpp index 93315c0bea6..e9bd1f465d3 100644 --- a/src/plugins/autotest/ctest/ctestoutputreader.cpp +++ b/src/plugins/autotest/ctest/ctestoutputreader.cpp @@ -71,7 +71,7 @@ private: }; CTestOutputReader::CTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory) : TestOutputReader(futureInterface, testApplication, buildDirectory) { diff --git a/src/plugins/autotest/ctest/ctestoutputreader.h b/src/plugins/autotest/ctest/ctestoutputreader.h index bbec3f70c77..205325fe1f7 100644 --- a/src/plugins/autotest/ctest/ctestoutputreader.h +++ b/src/plugins/autotest/ctest/ctestoutputreader.h @@ -28,6 +28,8 @@ #include +namespace Utils { class QtcProcess; } + namespace Autotest { namespace Internal { @@ -36,7 +38,7 @@ class CTestOutputReader final : public Autotest::TestOutputReader Q_DECLARE_TR_FUNCTIONS(Autotest::Internal::CTestOutputReader) public: CTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory); + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory); protected: void processOutputLine(const QByteArray &outputLineWithNewLine) final; diff --git a/src/plugins/autotest/gtest/gtestconfiguration.cpp b/src/plugins/autotest/gtest/gtestconfiguration.cpp index ff60f32171c..025040f54c8 100644 --- a/src/plugins/autotest/gtest/gtestconfiguration.cpp +++ b/src/plugins/autotest/gtest/gtestconfiguration.cpp @@ -38,7 +38,7 @@ namespace Autotest { namespace Internal { TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface &fi, - QProcess *app) const + Utils::QtcProcess *app) const { return new GTestOutputReader(fi, app, buildDirectory(), projectFile()); } diff --git a/src/plugins/autotest/gtest/gtestconfiguration.h b/src/plugins/autotest/gtest/gtestconfiguration.h index 822ad99fd1b..3844869a4b9 100644 --- a/src/plugins/autotest/gtest/gtestconfiguration.h +++ b/src/plugins/autotest/gtest/gtestconfiguration.h @@ -37,7 +37,7 @@ public: : DebuggableTestConfiguration(framework) {} TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const override; + Utils::QtcProcess *app) const override; QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override; Utils::Environment filteredEnvironment(const Utils::Environment &original) const override; }; diff --git a/src/plugins/autotest/gtest/gtestoutputreader.cpp b/src/plugins/autotest/gtest/gtestoutputreader.cpp index 997e7d2ddc2..0c9f0b87334 100644 --- a/src/plugins/autotest/gtest/gtestoutputreader.cpp +++ b/src/plugins/autotest/gtest/gtestoutputreader.cpp @@ -28,6 +28,7 @@ #include "../testtreemodel.h" #include "../testtreeitem.h" #include +#include #include #include @@ -37,18 +38,19 @@ namespace Autotest { namespace Internal { GTestOutputReader::GTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile) : TestOutputReader(futureInterface, testApplication, buildDirectory) , m_projectFile(projectFile) { if (m_testApplication) { - connect(m_testApplication, QOverload::of(&QProcess::finished), - this, [this] (int exitCode, QProcess::ExitStatus /*exitStatus*/) { + connect(m_testApplication, &Utils::QtcProcess::finished, + this, [this]() { + int exitCode = m_testApplication->exitCode(); if (exitCode == 1 && !m_description.isEmpty()) { createAndReportResult(tr("Running tests failed.\n %1\nExecutable: %2") - .arg(m_description).arg(id()), ResultType::MessageFatal); + .arg(m_description).arg(id()), ResultType::MessageFatal); } // on Windows abort() will result in normal termination, but exit code will be set to 3 if (Utils::HostOsInfo::isWindowsHost() && exitCode == 3) diff --git a/src/plugins/autotest/gtest/gtestoutputreader.h b/src/plugins/autotest/gtest/gtestoutputreader.h index 05688a4fa2b..f6d499dbed5 100644 --- a/src/plugins/autotest/gtest/gtestoutputreader.h +++ b/src/plugins/autotest/gtest/gtestoutputreader.h @@ -38,7 +38,7 @@ class GTestOutputReader : public TestOutputReader public: GTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile); protected: void processOutputLine(const QByteArray &outputLine) override; diff --git a/src/plugins/autotest/qtest/qttestconfiguration.cpp b/src/plugins/autotest/qtest/qttestconfiguration.cpp index 7f613702137..4ca1326ba52 100644 --- a/src/plugins/autotest/qtest/qttestconfiguration.cpp +++ b/src/plugins/autotest/qtest/qttestconfiguration.cpp @@ -38,7 +38,7 @@ namespace Autotest { namespace Internal { TestOutputReader *QtTestConfiguration::outputReader(const QFutureInterface &fi, - QProcess *app) const + Utils::QtcProcess *app) const { auto qtSettings = static_cast(framework()->testSettings()); const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value() diff --git a/src/plugins/autotest/qtest/qttestconfiguration.h b/src/plugins/autotest/qtest/qttestconfiguration.h index 8196665679c..83ac6d79a53 100644 --- a/src/plugins/autotest/qtest/qttestconfiguration.h +++ b/src/plugins/autotest/qtest/qttestconfiguration.h @@ -36,7 +36,7 @@ public: explicit QtTestConfiguration(ITestFramework *framework) : DebuggableTestConfiguration(framework) {} TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const override; + Utils::QtcProcess *app) const override; QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override; Utils::Environment filteredEnvironment(const Utils::Environment &original) const override; }; diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp index a6be21019d9..fc762bbe0a4 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.cpp +++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp @@ -126,7 +126,7 @@ static QString constructBenchmarkInformation(const QString &metric, double value } QtTestOutputReader::QtTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile, OutputMode mode, TestType type) diff --git a/src/plugins/autotest/qtest/qttestoutputreader.h b/src/plugins/autotest/qtest/qttestoutputreader.h index eff84dd4642..6ceabd508b5 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.h +++ b/src/plugins/autotest/qtest/qttestoutputreader.h @@ -48,7 +48,7 @@ public: }; QtTestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory, + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory, const Utils::FilePath &projectFile, OutputMode mode, TestType type); protected: void processOutputLine(const QByteArray &outputLine) override; diff --git a/src/plugins/autotest/quick/quicktestconfiguration.cpp b/src/plugins/autotest/quick/quicktestconfiguration.cpp index 8ede65e66bc..9cb1abb680e 100644 --- a/src/plugins/autotest/quick/quicktestconfiguration.cpp +++ b/src/plugins/autotest/quick/quicktestconfiguration.cpp @@ -44,7 +44,7 @@ QuickTestConfiguration::QuickTestConfiguration(ITestFramework *framework) } TestOutputReader *QuickTestConfiguration::outputReader(const QFutureInterface &fi, - QProcess *app) const + Utils::QtcProcess *app) const { auto qtSettings = static_cast(framework()->testSettings()); const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value() diff --git a/src/plugins/autotest/quick/quicktestconfiguration.h b/src/plugins/autotest/quick/quicktestconfiguration.h index 88f94c96df9..ca74633a912 100644 --- a/src/plugins/autotest/quick/quicktestconfiguration.h +++ b/src/plugins/autotest/quick/quicktestconfiguration.h @@ -35,7 +35,7 @@ class QuickTestConfiguration : public DebuggableTestConfiguration public: explicit QuickTestConfiguration(ITestFramework *framework); TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const override; + Utils::QtcProcess *app) const override; QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override; Utils::Environment filteredEnvironment(const Utils::Environment &original) const override; }; diff --git a/src/plugins/autotest/testconfiguration.h b/src/plugins/autotest/testconfiguration.h index a1a4240f3dd..e338280a954 100644 --- a/src/plugins/autotest/testconfiguration.h +++ b/src/plugins/autotest/testconfiguration.h @@ -35,9 +35,7 @@ #include #include -QT_BEGIN_NAMESPACE -class QProcess; -QT_END_NAMESPACE +namespace Utils { class QtcProcess; } namespace Autotest { namespace Internal { @@ -66,7 +64,7 @@ public: Utils::FilePath executableFilePath() const; virtual TestOutputReader *outputReader(const QFutureInterface &fi, - QProcess *app) const = 0; + Utils::QtcProcess *app) const = 0; virtual Utils::Environment filteredEnvironment(const Utils::Environment &original) const; ITestBase *testBase() const { return m_testBase; } diff --git a/src/plugins/autotest/testoutputreader.cpp b/src/plugins/autotest/testoutputreader.cpp index f2ad3bff054..fcd0ace2300 100644 --- a/src/plugins/autotest/testoutputreader.cpp +++ b/src/plugins/autotest/testoutputreader.cpp @@ -30,6 +30,7 @@ #include "testtreeitem.h" #include +#include #include #include @@ -46,11 +47,12 @@ Utils::FilePath TestOutputReader::constructSourceFilePath(const Utils::FilePath } TestOutputReader::TestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory) + Utils::QtcProcess *testApplication, + const Utils::FilePath &buildDirectory) : m_futureInterface(futureInterface) , m_testApplication(testApplication) , m_buildDir(buildDirectory) - , m_id(testApplication ? testApplication->program() : QString()) + , m_id(testApplication ? testApplication->commandLine().executable().toUserOutput() : QString()) { auto chopLineBreak = [](QByteArray line) { if (line.endsWith('\n')) @@ -61,17 +63,11 @@ TestOutputReader::TestOutputReader(const QFutureInterface &future }; if (m_testApplication) { - connect(m_testApplication, &QProcess::readyReadStandardOutput, - this, [chopLineBreak, this] () { - m_testApplication->setReadChannel(QProcess::StandardOutput); - while (m_testApplication->canReadLine()) - processStdOutput(chopLineBreak(m_testApplication->readLine())); + m_testApplication->setStdOutLineCallback([this, &chopLineBreak](const QString &line) { + processStdOutput(chopLineBreak(line.toUtf8())); }); - connect(m_testApplication, &QProcess::readyReadStandardError, - this, [chopLineBreak, this] () { - m_testApplication->setReadChannel(QProcess::StandardError); - while (m_testApplication->canReadLine()) - processStdError(chopLineBreak(m_testApplication->readLine())); + m_testApplication->setStdErrLineCallback([this, &chopLineBreak](const QString &line) { + processStdError(chopLineBreak(line.toUtf8())); }); } } diff --git a/src/plugins/autotest/testoutputreader.h b/src/plugins/autotest/testoutputreader.h index b3d7cc3476d..4f5d75b471c 100644 --- a/src/plugins/autotest/testoutputreader.h +++ b/src/plugins/autotest/testoutputreader.h @@ -29,9 +29,10 @@ #include #include -#include #include +namespace Utils { class QtcProcess; } + namespace Autotest { class TestOutputReader : public QObject @@ -39,7 +40,7 @@ class TestOutputReader : public QObject Q_OBJECT public: TestOutputReader(const QFutureInterface &futureInterface, - QProcess *testApplication, const Utils::FilePath &buildDirectory); + Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory); virtual ~TestOutputReader(); void processStdOutput(const QByteArray &outputLine); virtual void processStdError(const QByteArray &outputLine); @@ -67,7 +68,7 @@ protected: void reportResult(const TestResultPtr &result); QFutureInterface m_futureInterface; - QProcess *m_testApplication; // not owned + Utils::QtcProcess *m_testApplication; // not owned Utils::FilePath m_buildDir; QString m_id; QHash m_summary; diff --git a/src/plugins/autotest/testrunconfiguration.h b/src/plugins/autotest/testrunconfiguration.h index 451add1fa2b..ccb6282059b 100644 --- a/src/plugins/autotest/testrunconfiguration.h +++ b/src/plugins/autotest/testrunconfiguration.h @@ -66,7 +66,7 @@ public: ProjectExplorer::Runnable r; QTC_ASSERT(m_testConfig, return r); r.command.setExecutable(m_testConfig->executableFilePath()); - r.command.setArguments(m_testConfig->argumentsForTestRunner().join(' ')); + r.command.addArgs(m_testConfig->argumentsForTestRunner().join(' '), Utils::CommandLine::Raw); r.workingDirectory = m_testConfig->workingDirectory(); r.environment = m_testConfig->environment(); return r; diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index aa930eb595e..942730ba9d8 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -90,6 +90,8 @@ TestRunner::TestRunner() { s_instance = this; + m_cancelTimer.setSingleShot(true); + connect(&m_cancelTimer, &QTimer::timeout, this, [this]() { cancelCurrent(Timeout); }); connect(&m_futureWatcher, &QFutureWatcher::resultReadyAt, this, [this](int index) { emit testResultReady(m_futureWatcher.resultAt(index)); }); connect(&m_futureWatcher, &QFutureWatcher::finished, @@ -131,16 +133,17 @@ void TestRunner::runTest(TestRunMode mode, const ITestTreeItem *item) } } -static QString processInformation(const QProcess *proc) +static QString processInformation(const QtcProcess *proc) { QTC_ASSERT(proc, return QString()); - QString information("\nCommand line: " + proc->program() + ' ' + proc->arguments().join(' ')); + const Utils::CommandLine command = proc->commandLine(); + QString information("\nCommand line: " + command.executable().toUserOutput() + ' ' + command.arguments()); QStringList important = { "PATH" }; if (Utils::HostOsInfo::isLinuxHost()) important.append("LD_LIBRARY_PATH"); else if (Utils::HostOsInfo::isMacHost()) important.append({ "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH" }); - const QProcessEnvironment &environment = proc->processEnvironment(); + const Utils::Environment &environment = proc->environment(); for (const QString &var : important) information.append('\n' + var + ": " + environment.value(var)); return information; @@ -204,34 +207,35 @@ bool TestRunner::currentConfigValid() void TestRunner::setUpProcess() { QTC_ASSERT(m_currentConfig, return); - m_currentProcess = new QProcess; - m_currentProcess->setReadChannel(QProcess::StandardOutput); + m_currentProcess = new QtcProcess; if (m_currentConfig->testBase()->type() == ITestBase::Framework) { TestConfiguration *current = static_cast(m_currentConfig); - m_currentProcess->setProgram(current->executableFilePath().toString()); + m_currentProcess->setCommand({current->executableFilePath(), {}}); } else { TestToolConfiguration *current = static_cast(m_currentConfig); - m_currentProcess->setProgram(current->commandLine().executable().toString()); + m_currentProcess->setCommand({current->commandLine().executable(), {}}); } } void TestRunner::setUpProcessEnv() { + Utils::CommandLine command = m_currentProcess->commandLine(); if (m_currentConfig->testBase()->type() == ITestBase::Framework) { TestConfiguration *current = static_cast(m_currentConfig); QStringList omitted; - m_currentProcess->setArguments(current->argumentsForTestRunner(&omitted)); + command.addArgs(current->argumentsForTestRunner(&omitted).join(' '), Utils::CommandLine::Raw); if (!omitted.isEmpty()) { const QString &details = constructOmittedDetailsString(omitted); reportResult(ResultType::MessageWarn, details.arg(current->displayName())); } } else { TestToolConfiguration *current = static_cast(m_currentConfig); - m_currentProcess->setArguments(current->commandLine().splitArguments()); + command.setArguments(current->commandLine().arguments()); } + m_currentProcess->setCommand(command); - m_currentProcess->setWorkingDirectory(m_currentConfig->workingDirectory().toString()); + m_currentProcess->setWorkingDirectory(m_currentConfig->workingDirectory()); const Utils::Environment &original = m_currentConfig->environment(); Utils::Environment environment = m_currentConfig->filteredEnvironment(original); const Utils::EnvironmentItems removedVariables = Utils::filtered( @@ -243,7 +247,7 @@ void TestRunner::setUpProcessEnv() .arg(m_currentConfig->displayName()); reportResult(ResultType::MessageWarn, details); } - m_currentProcess->setProcessEnvironment(environment.toProcessEnvironment()); + m_currentProcess->setEnvironment(environment); } void TestRunner::scheduleNext() @@ -272,15 +276,16 @@ void TestRunner::scheduleNext() setUpProcessEnv(); - connect(m_currentProcess, QOverload::of(&QProcess::finished), + connect(m_currentProcess, &Utils::QtcProcess::finished, this, &TestRunner::onProcessFinished); const int timeout = AutotestPlugin::settings()->timeout; - QTimer::singleShot(timeout, m_currentProcess, [this]() { cancelCurrent(Timeout); }); + m_cancelTimer.setInterval(timeout); + m_cancelTimer.start(); - qCInfo(runnerLog) << "Command:" << m_currentProcess->program(); - qCInfo(runnerLog) << "Arguments:" << m_currentProcess->arguments(); + qCInfo(runnerLog) << "Command:" << m_currentProcess->commandLine().executable(); + qCInfo(runnerLog) << "Arguments:" << m_currentProcess->commandLine().arguments(); qCInfo(runnerLog) << "Working directory:" << m_currentProcess->workingDirectory(); - qCDebug(runnerLog) << "Environment:" << m_currentProcess->environment(); + qCDebug(runnerLog) << "Environment:" << m_currentProcess->environment().toStringList(); m_currentProcess->start(); if (!m_currentProcess->waitForStarted()) { @@ -355,7 +360,8 @@ void TestRunner::onProcessFinished() void TestRunner::resetInternalPointers() { delete m_currentOutputReader; - delete m_currentProcess; + if (m_currentProcess) + m_currentProcess->deleteLater(); delete m_currentConfig; m_currentOutputReader = nullptr; m_currentProcess = nullptr; @@ -812,6 +818,7 @@ void TestRunner::onBuildQueueFinished(bool success) void TestRunner::onFinished() { + m_cancelTimer.stop(); // if we've been canceled and we still have test configurations queued just throw them away qDeleteAll(m_selectedTests); m_selectedTests.clear(); diff --git a/src/plugins/autotest/testrunner.h b/src/plugins/autotest/testrunner.h index a95a78ab9d5..961312b6410 100644 --- a/src/plugins/autotest/testrunner.h +++ b/src/plugins/autotest/testrunner.h @@ -32,16 +32,17 @@ #include #include #include +#include QT_BEGIN_NAMESPACE class QCheckBox; class QComboBox; class QDialogButtonBox; class QLabel; -class QProcess; QT_END_NAMESPACE namespace ProjectExplorer { class Project; } +namespace Utils { class QtcProcess; } namespace Autotest { @@ -105,7 +106,7 @@ private: bool m_executingTests = false; bool m_canceled = false; ITestConfiguration *m_currentConfig = nullptr; - QProcess *m_currentProcess = nullptr; + Utils::QtcProcess *m_currentProcess = nullptr; TestOutputReader *m_currentOutputReader = nullptr; TestRunMode m_runMode = TestRunMode::None; @@ -116,6 +117,7 @@ private: QMetaObject::Connection m_finishDebugConnect; // temporarily used for handling of switching the current target QMetaObject::Connection m_targetConnect; + QTimer m_cancelTimer; bool m_skipTargetsCheck = false; };