AutoTest: Introduce ITestConfiguration

Preparation for an additional simpler test configuration
which needs to have the same common base.

Change-Id: I1800ed5d7301f1aea99eba6ef588a204697bd569
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Stenger
2020-10-13 11:37:37 +02:00
parent 55298cc211
commit 239a59c596
34 changed files with 373 additions and 310 deletions

View File

@@ -27,6 +27,7 @@
#include "autotestconstants.h"
#include "autotestplugin.h"
#include "itestframework.h"
#include "testoutputreader.h"
#include "testprojectsettings.h"
#include "testresultspane.h"
@@ -111,7 +112,7 @@ TestRunner::~TestRunner()
s_instance = nullptr;
}
void TestRunner::setSelectedTests(const QList<TestConfiguration *> &selected)
void TestRunner::setSelectedTests(const QList<ITestConfiguration *> &selected)
{
QTC_ASSERT(!m_executingTests, return);
qDeleteAll(m_selectedTests);
@@ -119,10 +120,10 @@ void TestRunner::setSelectedTests(const QList<TestConfiguration *> &selected)
m_selectedTests.append(selected);
}
void TestRunner::runTest(TestRunMode mode, const TestTreeItem *item)
void TestRunner::runTest(TestRunMode mode, const ITestTreeItem *item)
{
QTC_ASSERT(!m_executingTests, return);
TestConfiguration *configuration = item->asConfiguration(mode);
ITestConfiguration *configuration = item->asConfiguration(mode);
if (configuration) {
setSelectedTests({configuration});
@@ -145,14 +146,16 @@ static QString processInformation(const QProcess *proc)
return information;
}
static QString rcInfo(const TestConfiguration * const config)
static QString rcInfo(const ITestConfiguration * const config)
{
// FIXME early return for test tools
const TestConfiguration *current = static_cast<const TestConfiguration *>(config);
QString info;
if (config->isDeduced())
if (current->isDeduced())
info = TestRunner::tr("\nRun configuration: deduced from \"%1\"");
else
info = TestRunner::tr("\nRun configuration: \"%1\"");
return info.arg(config->runConfigDisplayName());
return info.arg(current->runConfigDisplayName());
}
static QString constructOmittedDetailsString(const QStringList &omitted)
@@ -170,6 +173,71 @@ static QString constructOmittedVariablesDetailsString(const Utils::EnvironmentIt
+ '\n' + removedVars.join('\n');
}
bool TestRunner::currentConfigValid()
{
if (true) { // FIXME do this for frameworks
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
QString commandFilePath = current->executableFilePath();
if (commandFilePath.isEmpty()) {
reportResult(ResultType::MessageFatal,
tr("Executable path is empty. (%1)").arg(current->displayName()));
delete m_currentConfig;
m_currentConfig = nullptr;
if (m_selectedTests.isEmpty()) {
if (m_fakeFutureInterface)
m_fakeFutureInterface->reportFinished();
onFinished();
} else {
onProcessFinished();
}
return false;
}
return true;
}
// FIXME check TestTools as well
return false;
}
void TestRunner::setUpProcess()
{
QTC_ASSERT(m_currentConfig, return);
if (true) { // FIXME do this for frameworks
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
m_currentProcess = new QProcess;
m_currentProcess->setReadChannel(QProcess::StandardOutput);
m_currentProcess->setProgram(current->executableFilePath());
}
// FIXME prepare for TestTools as well
}
void TestRunner::setUpProcessEnv()
{
if (true) { // do this for frameworks
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
QStringList omitted;
m_currentProcess->setArguments(current->argumentsForTestRunner(&omitted));
if (!omitted.isEmpty()) {
const QString &details = constructOmittedDetailsString(omitted);
reportResult(ResultType::MessageWarn, details.arg(current->displayName()));
}
m_currentProcess->setWorkingDirectory(current->workingDirectory());
const Utils::Environment &original = current->environment();
Utils::Environment environment = current->filteredEnvironment(original);
const Utils::EnvironmentItems removedVariables = Utils::filtered(
original.diff(environment), [](const Utils::EnvironmentItem &it) {
return it.operation == Utils::EnvironmentItem::Unset;
});
if (!removedVariables.isEmpty()) {
const QString &details = constructOmittedVariablesDetailsString(removedVariables)
.arg(current->displayName());
reportResult(ResultType::MessageWarn, details);
}
m_currentProcess->setProcessEnvironment(environment.toProcessEnvironment());
}
// FIXME prepare for TestTools as well
}
void TestRunner::scheduleNext()
{
QTC_ASSERT(!m_selectedTests.isEmpty(), onFinished(); return);
@@ -179,28 +247,14 @@ void TestRunner::scheduleNext()
m_currentConfig = m_selectedTests.dequeue();
QString commandFilePath = m_currentConfig->executableFilePath();
if (commandFilePath.isEmpty()) {
reportResult(ResultType::MessageFatal,
tr("Executable path is empty. (%1)").arg(m_currentConfig->displayName()));
delete m_currentConfig;
m_currentConfig = nullptr;
if (m_selectedTests.isEmpty()) {
if (m_fakeFutureInterface)
m_fakeFutureInterface->reportFinished();
onFinished();
} else {
onProcessFinished();
}
if (!currentConfigValid())
return;
}
if (!m_currentConfig->project())
onProcessFinished();
m_currentProcess = new QProcess;
m_currentProcess->setReadChannel(QProcess::StandardOutput);
m_currentProcess->setProgram(commandFilePath);
setUpProcess();
QTC_ASSERT(m_currentProcess, onProcessFinished(); return);
QTC_ASSERT(!m_currentOutputReader, delete m_currentOutputReader);
m_currentOutputReader = m_currentConfig->outputReader(*m_fakeFutureInterface, m_currentProcess);
QTC_ASSERT(m_currentOutputReader, onProcessFinished();return);
@@ -208,26 +262,7 @@ void TestRunner::scheduleNext()
connect(m_currentOutputReader, &TestOutputReader::newOutputLineAvailable,
TestResultsPane::instance(), &TestResultsPane::addOutputLine);
QStringList omitted;
m_currentProcess->setArguments(m_currentConfig->argumentsForTestRunner(&omitted));
if (!omitted.isEmpty()) {
const QString &details = constructOmittedDetailsString(omitted);
reportResult(ResultType::MessageWarn, details.arg(m_currentConfig->displayName()));
}
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(
original.diff(environment), [](const Utils::EnvironmentItem &it) {
return it.operation == Utils::EnvironmentItem::Unset;
});
if (!removedVariables.isEmpty()) {
const QString &details = constructOmittedVariablesDetailsString(removedVariables)
.arg(m_currentConfig->displayName());
reportResult(ResultType::MessageWarn, details);
}
m_currentProcess->setProcessEnvironment(environment.toProcessEnvironment());
setUpProcessEnv();
connect(m_currentProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &TestRunner::onProcessFinished);
@@ -432,7 +467,9 @@ int TestRunner::precheckTestConfigurations()
{
const bool omitWarnings = AutotestPlugin::settings()->omitRunConfigWarn;
int testCaseCount = 0;
for (TestConfiguration *config : m_selectedTests) {
for (ITestConfiguration *itc : qAsConst(m_selectedTests)) {
// FIXME handle test tools
TestConfiguration *config = static_cast<TestConfiguration *>(itc);
config->completeTestInformation(TestRunMode::Run);
if (config->project()) {
testCaseCount += config->testCaseCount();
@@ -441,7 +478,7 @@ int TestRunner::precheckTestConfigurations()
"Project's run configuration was deduced for \"%1\".\n"
"This might cause trouble during execution.\n"
"(deduced from \"%2\")");
message = message.arg(config->displayName()).arg(config->runConfigDisplayName());
message = message.arg(config->displayName(), config->runConfigDisplayName());
reportResult(ResultType::MessageWarn, message);
}
} else {
@@ -466,9 +503,11 @@ void TestRunner::onBuildSystemUpdated()
void TestRunner::runTests()
{
QList<TestConfiguration *> toBeRemoved;
QList<ITestConfiguration *> toBeRemoved;
bool projectChanged = false;
for (TestConfiguration *config : m_selectedTests) {
for (ITestConfiguration *itc : qAsConst(m_selectedTests)) {
// FIXME handle test tools
TestConfiguration *config = static_cast<TestConfiguration *>(itc);
config->completeTestInformation(TestRunMode::Run);
if (!config->project()) {
projectChanged = true;
@@ -480,7 +519,7 @@ void TestRunner::runTests()
toBeRemoved.append(config);
}
}
for (TestConfiguration *config : toBeRemoved)
for (ITestConfiguration *config : toBeRemoved)
m_selectedTests.removeOne(config);
qDeleteAll(toBeRemoved);
toBeRemoved.clear();
@@ -540,7 +579,9 @@ void TestRunner::debugTests()
// TODO improve to support more than one test configuration
QTC_ASSERT(m_selectedTests.size() == 1, onFinished();return);
TestConfiguration *config = m_selectedTests.first();
ITestConfiguration *itc = m_selectedTests.first();
// FIXME handle test tools as well
TestConfiguration *config = static_cast<TestConfiguration *>(itc);
config->completeTestInformation(TestRunMode::Debug);
if (!config->project()) {
reportResult(ResultType::MessageWarn,
@@ -562,13 +603,11 @@ void TestRunner::debugTests()
const QString &commandFilePath = config->executableFilePath();
if (commandFilePath.isEmpty()) {
reportResult(ResultType::MessageFatal, tr("Could not find command \"%1\". (%2)")
.arg(config->executableFilePath())
.arg(config->displayName()));
.arg(config->executableFilePath(), config->displayName()));
onFinished();
return;
}
QString errorMessage;
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
runControl->setRunConfiguration(config->runConfiguration());