forked from qt-creator/qt-creator
AutoTest: Use QtcProcess for test runner
Change-Id: I29b15a08a260aaf8d2c4071d5ea71d49902d8ef6 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -39,7 +39,7 @@ namespace Autotest {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
TestOutputReader *BoostTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *BoostTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
auto settings = static_cast<BoostTestSettings *>(framework()->testSettings());
|
auto settings = static_cast<BoostTestSettings *>(framework()->testSettings());
|
||||||
return new BoostTestOutputReader(fi, app, buildDirectory(), projectFile(),
|
return new BoostTestOutputReader(fi, app, buildDirectory(), projectFile(),
|
||||||
|
@@ -36,7 +36,7 @@ public:
|
|||||||
explicit BoostTestConfiguration(ITestFramework *framework)
|
explicit BoostTestConfiguration(ITestFramework *framework)
|
||||||
: DebuggableTestConfiguration(framework) {}
|
: DebuggableTestConfiguration(framework) {}
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const override;
|
Utils::QtcProcess *app) const override;
|
||||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||||
};
|
};
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include "boosttesttreeitem.h"
|
#include "boosttesttreeitem.h"
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
@@ -41,7 +42,7 @@ namespace Internal {
|
|||||||
static Q_LOGGING_CATEGORY(orLog, "qtc.autotest.boost.outputreader", QtWarningMsg)
|
static Q_LOGGING_CATEGORY(orLog, "qtc.autotest.boost.outputreader", QtWarningMsg)
|
||||||
|
|
||||||
BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication,
|
Utils::QtcProcess *testApplication,
|
||||||
const Utils::FilePath &buildDirectory,
|
const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile,
|
const Utils::FilePath &projectFile,
|
||||||
LogLevel log, ReportLevel report)
|
LogLevel log, ReportLevel report)
|
||||||
@@ -51,7 +52,7 @@ BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface<TestResultPt
|
|||||||
, m_reportLevel(report)
|
, m_reportLevel(report)
|
||||||
{
|
{
|
||||||
if (m_testApplication) {
|
if (m_testApplication) {
|
||||||
connect(m_testApplication, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
connect(m_testApplication, &Utils::QtcProcess::finished,
|
||||||
this, &BoostTestOutputReader::onFinished);
|
this, &BoostTestOutputReader::onFinished);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -405,7 +406,8 @@ TestResultPtr BoostTestOutputReader::createDefaultResult() const
|
|||||||
return TestResultPtr(result);
|
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) {
|
if (m_reportLevel == ReportLevel::No && m_testCaseCount != -1) {
|
||||||
int reportedFailsAndSkips = m_summary[ResultType::Fail] + m_summary[ResultType::Skip];
|
int reportedFailsAndSkips = m_summary[ResultType::Fail] + m_summary[ResultType::Skip];
|
||||||
m_summary.insert(ResultType::Pass, m_testCaseCount - reportedFailsAndSkips);
|
m_summary.insert(ResultType::Pass, m_testCaseCount - reportedFailsAndSkips);
|
||||||
|
@@ -39,7 +39,7 @@ class BoostTestOutputReader : public TestOutputReader
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory,
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile, LogLevel log, ReportLevel report);
|
const Utils::FilePath &projectFile, LogLevel log, ReportLevel report);
|
||||||
protected:
|
protected:
|
||||||
void processOutputLine(const QByteArray &outputLine) override;
|
void processOutputLine(const QByteArray &outputLine) override;
|
||||||
@@ -47,7 +47,7 @@ protected:
|
|||||||
TestResultPtr createDefaultResult() const override;
|
TestResultPtr createDefaultResult() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onFinished(int exitCode, QProcess::ExitStatus /*exitState*/);
|
void onFinished();
|
||||||
void sendCompleteInformation();
|
void sendCompleteInformation();
|
||||||
void handleMessageMatch(const QRegularExpressionMatch &match);
|
void handleMessageMatch(const QRegularExpressionMatch &match);
|
||||||
void reportNoOutputFinish(const QString &description, ResultType type);
|
void reportNoOutputFinish(const QString &description, ResultType type);
|
||||||
|
@@ -35,7 +35,8 @@
|
|||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
TestOutputReader *CatchConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi, QProcess *app) const
|
TestOutputReader *CatchConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
return new CatchOutputReader(fi, app, buildDirectory(), projectFile());
|
return new CatchOutputReader(fi, app, buildDirectory(), projectFile());
|
||||||
}
|
}
|
||||||
|
@@ -34,7 +34,7 @@ class CatchConfiguration : public DebuggableTestConfiguration
|
|||||||
public:
|
public:
|
||||||
CatchConfiguration(ITestFramework *framework) : DebuggableTestConfiguration(framework) {}
|
CatchConfiguration(ITestFramework *framework) : DebuggableTestConfiguration(framework) {}
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const override;
|
Utils::QtcProcess *app) const override;
|
||||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||||
};
|
};
|
||||||
|
@@ -49,7 +49,8 @@ namespace CatchXml {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CatchOutputReader::CatchOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
CatchOutputReader::CatchOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory,
|
Utils::QtcProcess *testApplication,
|
||||||
|
const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile)
|
const Utils::FilePath &projectFile)
|
||||||
: TestOutputReader (futureInterface, testApplication, buildDirectory)
|
: TestOutputReader (futureInterface, testApplication, buildDirectory)
|
||||||
, m_projectFile(projectFile)
|
, m_projectFile(projectFile)
|
||||||
|
@@ -39,7 +39,7 @@ class CatchOutputReader : public TestOutputReader
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
CatchOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
CatchOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory,
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile);
|
const Utils::FilePath &projectFile);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@@ -36,7 +36,7 @@ CTestConfiguration::CTestConfiguration(ITestBase *testBase)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TestOutputReader *CTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *CTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
return new CTestOutputReader(fi, app, workingDirectory());
|
return new CTestOutputReader(fi, app, workingDirectory());
|
||||||
}
|
}
|
||||||
|
@@ -36,7 +36,7 @@ public:
|
|||||||
explicit CTestConfiguration(ITestBase *testBase);
|
explicit CTestConfiguration(ITestBase *testBase);
|
||||||
|
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const final;
|
Utils::QtcProcess *app) const final;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -71,7 +71,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
CTestOutputReader::CTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
CTestOutputReader::CTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication,
|
Utils::QtcProcess *testApplication,
|
||||||
const Utils::FilePath &buildDirectory)
|
const Utils::FilePath &buildDirectory)
|
||||||
: TestOutputReader(futureInterface, testApplication, buildDirectory)
|
: TestOutputReader(futureInterface, testApplication, buildDirectory)
|
||||||
{
|
{
|
||||||
|
@@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
namespace Utils { class QtcProcess; }
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -36,7 +38,7 @@ class CTestOutputReader final : public Autotest::TestOutputReader
|
|||||||
Q_DECLARE_TR_FUNCTIONS(Autotest::Internal::CTestOutputReader)
|
Q_DECLARE_TR_FUNCTIONS(Autotest::Internal::CTestOutputReader)
|
||||||
public:
|
public:
|
||||||
CTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
CTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory);
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void processOutputLine(const QByteArray &outputLineWithNewLine) final;
|
void processOutputLine(const QByteArray &outputLineWithNewLine) final;
|
||||||
|
@@ -38,7 +38,7 @@ namespace Autotest {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
return new GTestOutputReader(fi, app, buildDirectory(), projectFile());
|
return new GTestOutputReader(fi, app, buildDirectory(), projectFile());
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ public:
|
|||||||
: DebuggableTestConfiguration(framework) {}
|
: DebuggableTestConfiguration(framework) {}
|
||||||
|
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const override;
|
Utils::QtcProcess *app) const override;
|
||||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||||
};
|
};
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "../testtreemodel.h"
|
#include "../testtreemodel.h"
|
||||||
#include "../testtreeitem.h"
|
#include "../testtreeitem.h"
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
@@ -37,18 +38,19 @@ namespace Autotest {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication,
|
Utils::QtcProcess *testApplication,
|
||||||
const Utils::FilePath &buildDirectory,
|
const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile)
|
const Utils::FilePath &projectFile)
|
||||||
: TestOutputReader(futureInterface, testApplication, buildDirectory)
|
: TestOutputReader(futureInterface, testApplication, buildDirectory)
|
||||||
, m_projectFile(projectFile)
|
, m_projectFile(projectFile)
|
||||||
{
|
{
|
||||||
if (m_testApplication) {
|
if (m_testApplication) {
|
||||||
connect(m_testApplication, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
connect(m_testApplication, &Utils::QtcProcess::finished,
|
||||||
this, [this] (int exitCode, QProcess::ExitStatus /*exitStatus*/) {
|
this, [this]() {
|
||||||
|
int exitCode = m_testApplication->exitCode();
|
||||||
if (exitCode == 1 && !m_description.isEmpty()) {
|
if (exitCode == 1 && !m_description.isEmpty()) {
|
||||||
createAndReportResult(tr("Running tests failed.\n %1\nExecutable: %2")
|
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
|
// on Windows abort() will result in normal termination, but exit code will be set to 3
|
||||||
if (Utils::HostOsInfo::isWindowsHost() && exitCode == 3)
|
if (Utils::HostOsInfo::isWindowsHost() && exitCode == 3)
|
||||||
|
@@ -38,7 +38,7 @@ class GTestOutputReader : public TestOutputReader
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory,
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile);
|
const Utils::FilePath &projectFile);
|
||||||
protected:
|
protected:
|
||||||
void processOutputLine(const QByteArray &outputLine) override;
|
void processOutputLine(const QByteArray &outputLine) override;
|
||||||
|
@@ -38,7 +38,7 @@ namespace Autotest {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
TestOutputReader *QtTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *QtTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
auto qtSettings = static_cast<QtTestSettings *>(framework()->testSettings());
|
auto qtSettings = static_cast<QtTestSettings *>(framework()->testSettings());
|
||||||
const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value()
|
const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value()
|
||||||
|
@@ -36,7 +36,7 @@ public:
|
|||||||
explicit QtTestConfiguration(ITestFramework *framework)
|
explicit QtTestConfiguration(ITestFramework *framework)
|
||||||
: DebuggableTestConfiguration(framework) {}
|
: DebuggableTestConfiguration(framework) {}
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const override;
|
Utils::QtcProcess *app) const override;
|
||||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||||
};
|
};
|
||||||
|
@@ -126,7 +126,7 @@ static QString constructBenchmarkInformation(const QString &metric, double value
|
|||||||
}
|
}
|
||||||
|
|
||||||
QtTestOutputReader::QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
QtTestOutputReader::QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication,
|
Utils::QtcProcess *testApplication,
|
||||||
const Utils::FilePath &buildDirectory,
|
const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile,
|
const Utils::FilePath &projectFile,
|
||||||
OutputMode mode, TestType type)
|
OutputMode mode, TestType type)
|
||||||
|
@@ -48,7 +48,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory,
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile, OutputMode mode, TestType type);
|
const Utils::FilePath &projectFile, OutputMode mode, TestType type);
|
||||||
protected:
|
protected:
|
||||||
void processOutputLine(const QByteArray &outputLine) override;
|
void processOutputLine(const QByteArray &outputLine) override;
|
||||||
|
@@ -44,7 +44,7 @@ QuickTestConfiguration::QuickTestConfiguration(ITestFramework *framework)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TestOutputReader *QuickTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *QuickTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
auto qtSettings = static_cast<QtTestSettings *>(framework()->testSettings());
|
auto qtSettings = static_cast<QtTestSettings *>(framework()->testSettings());
|
||||||
const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value()
|
const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value()
|
||||||
|
@@ -35,7 +35,7 @@ class QuickTestConfiguration : public DebuggableTestConfiguration
|
|||||||
public:
|
public:
|
||||||
explicit QuickTestConfiguration(ITestFramework *framework);
|
explicit QuickTestConfiguration(ITestFramework *framework);
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const override;
|
Utils::QtcProcess *app) const override;
|
||||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||||
};
|
};
|
||||||
|
@@ -35,9 +35,7 @@
|
|||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
namespace Utils { class QtcProcess; }
|
||||||
class QProcess;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -66,7 +64,7 @@ public:
|
|||||||
Utils::FilePath executableFilePath() const;
|
Utils::FilePath executableFilePath() const;
|
||||||
|
|
||||||
virtual TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
virtual TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const = 0;
|
Utils::QtcProcess *app) const = 0;
|
||||||
virtual Utils::Environment filteredEnvironment(const Utils::Environment &original) const;
|
virtual Utils::Environment filteredEnvironment(const Utils::Environment &original) const;
|
||||||
|
|
||||||
ITestBase *testBase() const { return m_testBase; }
|
ITestBase *testBase() const { return m_testBase; }
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include "testtreeitem.h"
|
#include "testtreeitem.h"
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@@ -46,11 +47,12 @@ Utils::FilePath TestOutputReader::constructSourceFilePath(const Utils::FilePath
|
|||||||
}
|
}
|
||||||
|
|
||||||
TestOutputReader::TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
TestOutputReader::TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory)
|
Utils::QtcProcess *testApplication,
|
||||||
|
const Utils::FilePath &buildDirectory)
|
||||||
: m_futureInterface(futureInterface)
|
: m_futureInterface(futureInterface)
|
||||||
, m_testApplication(testApplication)
|
, m_testApplication(testApplication)
|
||||||
, m_buildDir(buildDirectory)
|
, m_buildDir(buildDirectory)
|
||||||
, m_id(testApplication ? testApplication->program() : QString())
|
, m_id(testApplication ? testApplication->commandLine().executable().toUserOutput() : QString())
|
||||||
{
|
{
|
||||||
auto chopLineBreak = [](QByteArray line) {
|
auto chopLineBreak = [](QByteArray line) {
|
||||||
if (line.endsWith('\n'))
|
if (line.endsWith('\n'))
|
||||||
@@ -61,17 +63,11 @@ TestOutputReader::TestOutputReader(const QFutureInterface<TestResultPtr> &future
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (m_testApplication) {
|
if (m_testApplication) {
|
||||||
connect(m_testApplication, &QProcess::readyReadStandardOutput,
|
m_testApplication->setStdOutLineCallback([this, &chopLineBreak](const QString &line) {
|
||||||
this, [chopLineBreak, this] () {
|
processStdOutput(chopLineBreak(line.toUtf8()));
|
||||||
m_testApplication->setReadChannel(QProcess::StandardOutput);
|
|
||||||
while (m_testApplication->canReadLine())
|
|
||||||
processStdOutput(chopLineBreak(m_testApplication->readLine()));
|
|
||||||
});
|
});
|
||||||
connect(m_testApplication, &QProcess::readyReadStandardError,
|
m_testApplication->setStdErrLineCallback([this, &chopLineBreak](const QString &line) {
|
||||||
this, [chopLineBreak, this] () {
|
processStdError(chopLineBreak(line.toUtf8()));
|
||||||
m_testApplication->setReadChannel(QProcess::StandardError);
|
|
||||||
while (m_testApplication->canReadLine())
|
|
||||||
processStdError(chopLineBreak(m_testApplication->readLine()));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,9 +29,10 @@
|
|||||||
|
|
||||||
#include <QFutureInterface>
|
#include <QFutureInterface>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QProcess>
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Utils { class QtcProcess; }
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
|
|
||||||
class TestOutputReader : public QObject
|
class TestOutputReader : public QObject
|
||||||
@@ -39,7 +40,7 @@ class TestOutputReader : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory);
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory);
|
||||||
virtual ~TestOutputReader();
|
virtual ~TestOutputReader();
|
||||||
void processStdOutput(const QByteArray &outputLine);
|
void processStdOutput(const QByteArray &outputLine);
|
||||||
virtual void processStdError(const QByteArray &outputLine);
|
virtual void processStdError(const QByteArray &outputLine);
|
||||||
@@ -67,7 +68,7 @@ protected:
|
|||||||
|
|
||||||
void reportResult(const TestResultPtr &result);
|
void reportResult(const TestResultPtr &result);
|
||||||
QFutureInterface<TestResultPtr> m_futureInterface;
|
QFutureInterface<TestResultPtr> m_futureInterface;
|
||||||
QProcess *m_testApplication; // not owned
|
Utils::QtcProcess *m_testApplication; // not owned
|
||||||
Utils::FilePath m_buildDir;
|
Utils::FilePath m_buildDir;
|
||||||
QString m_id;
|
QString m_id;
|
||||||
QHash<ResultType, int> m_summary;
|
QHash<ResultType, int> m_summary;
|
||||||
|
@@ -66,7 +66,7 @@ public:
|
|||||||
ProjectExplorer::Runnable r;
|
ProjectExplorer::Runnable r;
|
||||||
QTC_ASSERT(m_testConfig, return r);
|
QTC_ASSERT(m_testConfig, return r);
|
||||||
r.command.setExecutable(m_testConfig->executableFilePath());
|
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.workingDirectory = m_testConfig->workingDirectory();
|
||||||
r.environment = m_testConfig->environment();
|
r.environment = m_testConfig->environment();
|
||||||
return r;
|
return r;
|
||||||
|
@@ -90,6 +90,8 @@ TestRunner::TestRunner()
|
|||||||
{
|
{
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
|
|
||||||
|
m_cancelTimer.setSingleShot(true);
|
||||||
|
connect(&m_cancelTimer, &QTimer::timeout, this, [this]() { cancelCurrent(Timeout); });
|
||||||
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::resultReadyAt,
|
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::resultReadyAt,
|
||||||
this, [this](int index) { emit testResultReady(m_futureWatcher.resultAt(index)); });
|
this, [this](int index) { emit testResultReady(m_futureWatcher.resultAt(index)); });
|
||||||
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::finished,
|
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::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());
|
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" };
|
QStringList important = { "PATH" };
|
||||||
if (Utils::HostOsInfo::isLinuxHost())
|
if (Utils::HostOsInfo::isLinuxHost())
|
||||||
important.append("LD_LIBRARY_PATH");
|
important.append("LD_LIBRARY_PATH");
|
||||||
else if (Utils::HostOsInfo::isMacHost())
|
else if (Utils::HostOsInfo::isMacHost())
|
||||||
important.append({ "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH" });
|
important.append({ "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH" });
|
||||||
const QProcessEnvironment &environment = proc->processEnvironment();
|
const Utils::Environment &environment = proc->environment();
|
||||||
for (const QString &var : important)
|
for (const QString &var : important)
|
||||||
information.append('\n' + var + ": " + environment.value(var));
|
information.append('\n' + var + ": " + environment.value(var));
|
||||||
return information;
|
return information;
|
||||||
@@ -204,34 +207,35 @@ bool TestRunner::currentConfigValid()
|
|||||||
void TestRunner::setUpProcess()
|
void TestRunner::setUpProcess()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_currentConfig, return);
|
QTC_ASSERT(m_currentConfig, return);
|
||||||
m_currentProcess = new QProcess;
|
m_currentProcess = new QtcProcess;
|
||||||
m_currentProcess->setReadChannel(QProcess::StandardOutput);
|
|
||||||
if (m_currentConfig->testBase()->type() == ITestBase::Framework) {
|
if (m_currentConfig->testBase()->type() == ITestBase::Framework) {
|
||||||
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
|
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
|
||||||
m_currentProcess->setProgram(current->executableFilePath().toString());
|
m_currentProcess->setCommand({current->executableFilePath(), {}});
|
||||||
} else {
|
} else {
|
||||||
TestToolConfiguration *current = static_cast<TestToolConfiguration *>(m_currentConfig);
|
TestToolConfiguration *current = static_cast<TestToolConfiguration *>(m_currentConfig);
|
||||||
m_currentProcess->setProgram(current->commandLine().executable().toString());
|
m_currentProcess->setCommand({current->commandLine().executable(), {}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestRunner::setUpProcessEnv()
|
void TestRunner::setUpProcessEnv()
|
||||||
{
|
{
|
||||||
|
Utils::CommandLine command = m_currentProcess->commandLine();
|
||||||
if (m_currentConfig->testBase()->type() == ITestBase::Framework) {
|
if (m_currentConfig->testBase()->type() == ITestBase::Framework) {
|
||||||
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
|
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
|
||||||
|
|
||||||
QStringList omitted;
|
QStringList omitted;
|
||||||
m_currentProcess->setArguments(current->argumentsForTestRunner(&omitted));
|
command.addArgs(current->argumentsForTestRunner(&omitted).join(' '), Utils::CommandLine::Raw);
|
||||||
if (!omitted.isEmpty()) {
|
if (!omitted.isEmpty()) {
|
||||||
const QString &details = constructOmittedDetailsString(omitted);
|
const QString &details = constructOmittedDetailsString(omitted);
|
||||||
reportResult(ResultType::MessageWarn, details.arg(current->displayName()));
|
reportResult(ResultType::MessageWarn, details.arg(current->displayName()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TestToolConfiguration *current = static_cast<TestToolConfiguration *>(m_currentConfig);
|
TestToolConfiguration *current = static_cast<TestToolConfiguration *>(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();
|
const Utils::Environment &original = m_currentConfig->environment();
|
||||||
Utils::Environment environment = m_currentConfig->filteredEnvironment(original);
|
Utils::Environment environment = m_currentConfig->filteredEnvironment(original);
|
||||||
const Utils::EnvironmentItems removedVariables = Utils::filtered(
|
const Utils::EnvironmentItems removedVariables = Utils::filtered(
|
||||||
@@ -243,7 +247,7 @@ void TestRunner::setUpProcessEnv()
|
|||||||
.arg(m_currentConfig->displayName());
|
.arg(m_currentConfig->displayName());
|
||||||
reportResult(ResultType::MessageWarn, details);
|
reportResult(ResultType::MessageWarn, details);
|
||||||
}
|
}
|
||||||
m_currentProcess->setProcessEnvironment(environment.toProcessEnvironment());
|
m_currentProcess->setEnvironment(environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestRunner::scheduleNext()
|
void TestRunner::scheduleNext()
|
||||||
@@ -272,15 +276,16 @@ void TestRunner::scheduleNext()
|
|||||||
|
|
||||||
setUpProcessEnv();
|
setUpProcessEnv();
|
||||||
|
|
||||||
connect(m_currentProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
connect(m_currentProcess, &Utils::QtcProcess::finished,
|
||||||
this, &TestRunner::onProcessFinished);
|
this, &TestRunner::onProcessFinished);
|
||||||
const int timeout = AutotestPlugin::settings()->timeout;
|
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) << "Command:" << m_currentProcess->commandLine().executable();
|
||||||
qCInfo(runnerLog) << "Arguments:" << m_currentProcess->arguments();
|
qCInfo(runnerLog) << "Arguments:" << m_currentProcess->commandLine().arguments();
|
||||||
qCInfo(runnerLog) << "Working directory:" << m_currentProcess->workingDirectory();
|
qCInfo(runnerLog) << "Working directory:" << m_currentProcess->workingDirectory();
|
||||||
qCDebug(runnerLog) << "Environment:" << m_currentProcess->environment();
|
qCDebug(runnerLog) << "Environment:" << m_currentProcess->environment().toStringList();
|
||||||
|
|
||||||
m_currentProcess->start();
|
m_currentProcess->start();
|
||||||
if (!m_currentProcess->waitForStarted()) {
|
if (!m_currentProcess->waitForStarted()) {
|
||||||
@@ -355,7 +360,8 @@ void TestRunner::onProcessFinished()
|
|||||||
void TestRunner::resetInternalPointers()
|
void TestRunner::resetInternalPointers()
|
||||||
{
|
{
|
||||||
delete m_currentOutputReader;
|
delete m_currentOutputReader;
|
||||||
delete m_currentProcess;
|
if (m_currentProcess)
|
||||||
|
m_currentProcess->deleteLater();
|
||||||
delete m_currentConfig;
|
delete m_currentConfig;
|
||||||
m_currentOutputReader = nullptr;
|
m_currentOutputReader = nullptr;
|
||||||
m_currentProcess = nullptr;
|
m_currentProcess = nullptr;
|
||||||
@@ -812,6 +818,7 @@ void TestRunner::onBuildQueueFinished(bool success)
|
|||||||
|
|
||||||
void TestRunner::onFinished()
|
void TestRunner::onFinished()
|
||||||
{
|
{
|
||||||
|
m_cancelTimer.stop();
|
||||||
// if we've been canceled and we still have test configurations queued just throw them away
|
// if we've been canceled and we still have test configurations queued just throw them away
|
||||||
qDeleteAll(m_selectedTests);
|
qDeleteAll(m_selectedTests);
|
||||||
m_selectedTests.clear();
|
m_selectedTests.clear();
|
||||||
|
@@ -32,16 +32,17 @@
|
|||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QQueue>
|
#include <QQueue>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QDialogButtonBox;
|
class QDialogButtonBox;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QProcess;
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace ProjectExplorer { class Project; }
|
namespace ProjectExplorer { class Project; }
|
||||||
|
namespace Utils { class QtcProcess; }
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ private:
|
|||||||
bool m_executingTests = false;
|
bool m_executingTests = false;
|
||||||
bool m_canceled = false;
|
bool m_canceled = false;
|
||||||
ITestConfiguration *m_currentConfig = nullptr;
|
ITestConfiguration *m_currentConfig = nullptr;
|
||||||
QProcess *m_currentProcess = nullptr;
|
Utils::QtcProcess *m_currentProcess = nullptr;
|
||||||
TestOutputReader *m_currentOutputReader = nullptr;
|
TestOutputReader *m_currentOutputReader = nullptr;
|
||||||
TestRunMode m_runMode = TestRunMode::None;
|
TestRunMode m_runMode = TestRunMode::None;
|
||||||
|
|
||||||
@@ -116,6 +117,7 @@ private:
|
|||||||
QMetaObject::Connection m_finishDebugConnect;
|
QMetaObject::Connection m_finishDebugConnect;
|
||||||
// temporarily used for handling of switching the current target
|
// temporarily used for handling of switching the current target
|
||||||
QMetaObject::Connection m_targetConnect;
|
QMetaObject::Connection m_targetConnect;
|
||||||
|
QTimer m_cancelTimer;
|
||||||
bool m_skipTargetsCheck = false;
|
bool m_skipTargetsCheck = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user