AutoTest: Handle async updates of executable information

When opening or creating a project for the first time the
executable path of the application targets may be empty
until the build system has updated this after the first
successful build.
This update happens asynchronously, so we might need to
postpone the test execution a bit and wait for the
respective update.

Change-Id: I63b5c45f6ecb194020ea36bbb5c9486a4dcc004c
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Christian Stenger
2020-03-17 09:23:55 +01:00
parent 216de34207
commit 0f60f120d2
2 changed files with 41 additions and 0 deletions

View File

@@ -44,6 +44,7 @@
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildmanager.h> #include <projectexplorer/buildmanager.h>
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorersettings.h> #include <projectexplorer/projectexplorersettings.h>
@@ -64,6 +65,7 @@
#include <QFutureInterface> #include <QFutureInterface>
#include <QLabel> #include <QLabel>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QPointer>
#include <QProcess> #include <QProcess>
#include <QPushButton> #include <QPushButton>
#include <QTimer> #include <QTimer>
@@ -317,6 +319,7 @@ void TestRunner::resetInternalPointers()
void TestRunner::prepareToRunTests(TestRunMode mode) void TestRunner::prepareToRunTests(TestRunMode mode)
{ {
QTC_ASSERT(!m_executingTests, return); QTC_ASSERT(!m_executingTests, return);
m_skipTargetsCheck = false;
m_runMode = mode; m_runMode = mode;
ProjectExplorer::Internal::ProjectExplorerSettings projectExplorerSettings = ProjectExplorer::Internal::ProjectExplorerSettings projectExplorerSettings =
ProjectExplorerPlugin::projectExplorerSettings(); ProjectExplorerPlugin::projectExplorerSettings();
@@ -448,6 +451,15 @@ int TestRunner::precheckTestConfigurations()
return testCaseCount; return testCaseCount;
} }
void TestRunner::onBuildSystemUpdated()
{
Target *target = SessionManager::startupTarget();
if (QTC_GUARD(target))
disconnect(target, &Target::buildSystemUpdated, this, &TestRunner::onBuildSystemUpdated);
m_skipTargetsCheck = true;
runOrDebugTests();
}
void TestRunner::runTests() void TestRunner::runTests()
{ {
QList<TestConfiguration *> toBeRemoved; QList<TestConfiguration *> toBeRemoved;
@@ -619,8 +631,34 @@ void TestRunner::debugTests()
AutotestPlugin::popupResultsPane(); AutotestPlugin::popupResultsPane();
} }
static bool executablesEmpty()
{
Target *target = SessionManager::startupTarget();
const QList<RunConfiguration *> configs = target->runConfigurations();
QTC_ASSERT(!configs.isEmpty(), return false);
if (auto execAspect = configs.first()->aspect<ExecutableAspect>())
return execAspect->executable().isEmpty();
return false;
}
void TestRunner::runOrDebugTests() void TestRunner::runOrDebugTests()
{ {
if (!m_skipTargetsCheck) {
if (executablesEmpty()) {
m_skipTargetsCheck = true;
Target * target = SessionManager::startupTarget();
QTimer::singleShot(5000, this, [this, target = QPointer<Target>(target)]() {
if (target) {
disconnect(target, &Target::buildSystemUpdated,
this, &TestRunner::onBuildSystemUpdated);
}
runOrDebugTests();
});
connect(target, &Target::buildSystemUpdated, this, &TestRunner::onBuildSystemUpdated);
return;
}
}
switch (m_runMode) { switch (m_runMode) {
case TestRunMode::Run: case TestRunMode::Run:
case TestRunMode::RunWithoutDeploy: case TestRunMode::RunWithoutDeploy:

View File

@@ -93,6 +93,8 @@ private:
void runOrDebugTests(); void runOrDebugTests();
void reportResult(ResultType type, const QString &description); void reportResult(ResultType type, const QString &description);
explicit TestRunner(QObject *parent = nullptr); explicit TestRunner(QObject *parent = nullptr);
bool postponeTestRunWithEmptyExecutable(ProjectExplorer::Project *project);
void onBuildSystemUpdated();
QFutureWatcher<TestResultPtr> m_futureWatcher; QFutureWatcher<TestResultPtr> m_futureWatcher;
QFutureInterface<TestResultPtr> *m_fakeFutureInterface = nullptr; QFutureInterface<TestResultPtr> *m_fakeFutureInterface = nullptr;
@@ -111,6 +113,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;
bool m_skipTargetsCheck = false;
}; };
class RunConfigurationSelectionDialog : public QDialog class RunConfigurationSelectionDialog : public QDialog