Commit 19c8c9bc authored by Christian Stenger's avatar Christian Stenger

AutoTest: Avoid passing around pointer without owner...

...when using signals and slots between threads.

Change-Id: Ib1ce607e225cb8d9973393c5bdaeebaa6e30bb41
Reviewed-by: default avatarEike Ziller <eike.ziller@theqtcompany.com>
parent ba61f294
......@@ -130,7 +130,7 @@ static QString constructBenchmarkInformation(const QString &metric, double value
.arg(iterations);
}
TestOutputReader::TestOutputReader(QFutureInterface<TestResult *> futureInterface,
TestOutputReader::TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
QProcess *testApplication, const QString &buildDirectory)
: m_futureInterface(futureInterface)
, m_testApplication(testApplication)
......@@ -139,7 +139,7 @@ TestOutputReader::TestOutputReader(QFutureInterface<TestResult *> futureInterfac
connect(m_testApplication, &QProcess::readyRead, this, &TestOutputReader::processOutput);
}
QtTestOutputReader::QtTestOutputReader(QFutureInterface<TestResult *> futureInterface,
QtTestOutputReader::QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
QProcess *testApplication, const QString &buildDirectory)
: TestOutputReader(futureInterface, testApplication, buildDirectory)
{
......@@ -174,14 +174,14 @@ void QtTestOutputReader::processOutput()
if (currentTag == QStringLiteral("TestCase")) {
m_className = m_xmlReader.attributes().value(QStringLiteral("name")).toString();
QTC_ASSERT(!m_className.isEmpty(), continue);
auto testResult = new QTestResult(m_className);
TestResultPtr testResult = TestResultPtr(new QTestResult(m_className));
testResult->setResult(Result::MessageTestCaseStart);
testResult->setDescription(tr("Executing test case %1").arg(m_className));
m_futureInterface.reportResult(testResult);
} else if (currentTag == QStringLiteral("TestFunction")) {
m_testCase = m_xmlReader.attributes().value(QStringLiteral("name")).toString();
QTC_ASSERT(!m_testCase.isEmpty(), continue);
auto testResult = new QTestResult();
TestResultPtr testResult = TestResultPtr(new QTestResult());
testResult->setResult(Result::MessageCurrentTest);
testResult->setDescription(tr("Entering test function %1::%2").arg(m_className,
m_testCase));
......@@ -263,7 +263,7 @@ void QtTestOutputReader::processOutput()
const QStringRef currentTag = m_xmlReader.name();
if (currentTag == QStringLiteral("TestFunction")) {
if (!m_duration.isEmpty()) {
auto testResult = new QTestResult(m_className);
TestResultPtr testResult = TestResultPtr(new QTestResult(m_className));
testResult->setTestCase(m_testCase);
testResult->setResult(Result::MessageInternal);
testResult->setDescription(tr("Execution took %1 ms.").arg(m_duration));
......@@ -271,14 +271,14 @@ void QtTestOutputReader::processOutput()
}
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
} else if (currentTag == QStringLiteral("TestCase")) {
auto testResult = new QTestResult(m_className);
TestResultPtr testResult = TestResultPtr(new QTestResult(m_className));
testResult->setResult(Result::MessageTestCaseEnd);
testResult->setDescription(
m_duration.isEmpty() ? tr("Test finished.")
: tr("Test execution took %1 ms.").arg(m_duration));
m_futureInterface.reportResult(testResult);
} else if (validEndTags.contains(currentTag.toString())) {
auto testResult = new QTestResult(m_className);
TestResultPtr testResult = TestResultPtr(new QTestResult(m_className));
testResult->setTestCase(m_testCase);
testResult->setDataTag(m_dataTag);
testResult->setResult(m_result);
......@@ -296,7 +296,7 @@ void QtTestOutputReader::processOutput()
}
}
GTestOutputReader::GTestOutputReader(QFutureInterface<TestResult *> futureInterface,
GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
QProcess *testApplication, const QString &buildDirectory)
: TestOutputReader(futureInterface, testApplication, buildDirectory)
{
......@@ -342,13 +342,13 @@ void GTestOutputReader::processOutput()
m_iteration = iterations.cap(1).toInt();
m_description.clear();
} else if (line.startsWith(QStringLiteral("Note:"))) {
auto testResult = new GTestResult();
TestResultPtr testResult = TestResultPtr(new GTestResult());
testResult->setResult(Result::MessageInternal);
testResult->setDescription(line);
m_futureInterface.reportResult(testResult);
m_description.clear();
} else if (disabledTests.exactMatch(line)) {
auto testResult = new GTestResult();
TestResultPtr testResult = TestResultPtr(new GTestResult());
testResult->setResult(Result::MessageDisabledTests);
int disabled = disabledTests.cap(1).toInt();
testResult->setDescription(tr("You have %n disabled test(s).", 0, disabled));
......@@ -360,7 +360,7 @@ void GTestOutputReader::processOutput()
}
if (testEnds.exactMatch(line)) {
auto testResult = new GTestResult(m_currentTestName);
TestResultPtr testResult = TestResultPtr(new GTestResult(m_currentTestName));
testResult->setTestCase(m_currentTestSet);
testResult->setResult(Result::MessageTestCaseEnd);
testResult->setDescription(tr("Test execution took %1").arg(testEnds.cap(2)));
......@@ -369,7 +369,7 @@ void GTestOutputReader::processOutput()
m_currentTestSet.clear();
} else if (newTestStarts.exactMatch(line)) {
m_currentTestName = newTestStarts.cap(1);
auto testResult = new GTestResult(m_currentTestName);
TestResultPtr testResult = TestResultPtr(new GTestResult(m_currentTestName));
if (m_iteration > 1) {
testResult->setResult(Result::MessageTestCaseRepetition);
testResult->setDescription(tr("Repeating test case %1 (iteration %2)")
......@@ -381,26 +381,26 @@ void GTestOutputReader::processOutput()
m_futureInterface.reportResult(testResult);
} else if (newTestSetStarts.exactMatch(line)) {
m_currentTestSet = newTestSetStarts.cap(1);
auto testResult = new GTestResult();
TestResultPtr testResult = TestResultPtr(new GTestResult());
testResult->setResult(Result::MessageCurrentTest);
testResult->setDescription(tr("Entering test set %1").arg(m_currentTestSet));
m_futureInterface.reportResult(testResult);
m_description.clear();
} else if (testSetSuccess.exactMatch(line)) {
auto testResult = new GTestResult(m_currentTestName);
TestResultPtr testResult = TestResultPtr(new GTestResult(m_currentTestName));
testResult->setTestCase(m_currentTestSet);
testResult->setResult(Result::Pass);
testResult->setDescription(m_description);
m_futureInterface.reportResult(testResult);
m_description.clear();
testResult = new GTestResult(m_currentTestName);
testResult = TestResultPtr(new GTestResult(m_currentTestName));
testResult->setTestCase(m_currentTestSet);
testResult->setResult(Result::MessageInternal);
testResult->setDescription(tr("Execution took %1.").arg(testSetSuccess.cap(2)));
m_futureInterface.reportResult(testResult);
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
} else if (testSetFail.exactMatch(line)) {
auto testResult = new GTestResult(m_currentTestName);
TestResultPtr testResult = TestResultPtr(new GTestResult(m_currentTestName));
testResult->setTestCase(m_currentTestSet);
testResult->setResult(Result::Fail);
m_description.chop(1);
......@@ -418,7 +418,7 @@ void GTestOutputReader::processOutput()
}
m_futureInterface.reportResult(testResult);
m_description.clear();
testResult = new GTestResult(m_currentTestName);
testResult = TestResultPtr(new GTestResult(m_currentTestName));
testResult->setTestCase(m_currentTestSet);
testResult->setResult(Result::MessageInternal);
testResult->setDescription(tr("Execution took %1.").arg(testSetFail.cap(2)));
......
......@@ -44,12 +44,12 @@ class TestOutputReader : public QObject
{
Q_OBJECT
public:
TestOutputReader(QFutureInterface<TestResult *> futureInterface,
TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
QProcess *testApplication, const QString &buildDirectory);
protected:
virtual void processOutput() = 0;
QFutureInterface<TestResult *> m_futureInterface;
QFutureInterface<TestResultPtr> m_futureInterface;
QProcess *m_testApplication; // not owned
QString m_buildDir;
};
......@@ -57,7 +57,7 @@ protected:
class QtTestOutputReader : public TestOutputReader
{
public:
QtTestOutputReader(QFutureInterface<TestResult *> futureInterface,
QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
QProcess *testApplication, const QString &buildDirectory);
protected:
......@@ -89,7 +89,7 @@ private:
class GTestOutputReader : public TestOutputReader
{
public:
GTestOutputReader(QFutureInterface<TestResult *> futureInterface,
GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
QProcess *testApplication, const QString &buildDirectory);
protected:
......
......@@ -31,6 +31,7 @@
#include <QString>
#include <QColor>
#include <QMetaType>
#include <QSharedPointer>
namespace Autotest {
namespace Internal {
......@@ -104,6 +105,8 @@ private:
// environment?
};
using TestResultPtr = QSharedPointer<TestResult>;
class FaultyTestResult : public TestResult
{
public:
......
......@@ -33,14 +33,13 @@ namespace Internal {
/********************************* TestResultItem ******************************************/
TestResultItem::TestResultItem(TestResult *testResult)
TestResultItem::TestResultItem(const TestResultPtr &testResult)
: m_testResult(testResult)
{
}
TestResultItem::~TestResultItem()
{
delete m_testResult;
}
static QIcon testResultIcon(Result::Type result) {
......@@ -138,7 +137,7 @@ QVariant TestResultModel::data(const QModelIndex &idx, int role) const
return QVariant();
}
void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand)
void TestResultModel::addTestResult(const TestResultPtr &testResult, bool autoExpand)
{
const bool isCurrentTestMssg = testResult->result() == Result::MessageCurrentTest;
......@@ -158,7 +157,6 @@ void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand)
if (result && result->result() == Result::MessageCurrentTest) {
current->updateDescription(testResult->description());
emit dataChanged(current->index(), current->index());
delete testResult;
return;
}
}
......
......@@ -41,15 +41,15 @@ namespace Internal {
class TestResultItem : public Utils::TreeItem
{
public:
explicit TestResultItem(TestResult *testResult);
explicit TestResultItem(const TestResultPtr &testResult);
~TestResultItem();
QVariant data(int column, int role) const;
const TestResult *testResult() const { return m_testResult; }
const TestResult *testResult() const { return m_testResult.data(); }
void updateDescription(const QString &description);
void updateResult();
private:
TestResult *m_testResult;
TestResultPtr m_testResult;
};
class TestResultModel : public Utils::TreeModel
......@@ -58,7 +58,7 @@ public:
explicit TestResultModel(QObject *parent = 0);
QVariant data(const QModelIndex &idx, int role) const;
void addTestResult(TestResult *testResult, bool autoExpand = false);
void addTestResult(const TestResultPtr &testResult, bool autoExpand = false);
void removeCurrentTestMessage();
void clearTestResults();
......
......@@ -200,7 +200,7 @@ TestResultsPane::~TestResultsPane()
m_instance = 0;
}
void TestResultsPane::addTestResult(TestResult *result)
void TestResultsPane::addTestResult(const TestResultPtr &result)
{
const QScrollBar *scrollBar = m_treeView->verticalScrollBar();
m_atEnd = scrollBar ? scrollBar->value() == scrollBar->maximum() : true;
......
......@@ -26,6 +26,8 @@
#ifndef TESTRESULTSPANE_H
#define TESTRESULTSPANE_H
#include "testresult.h"
#include <coreplugin/ioutputpane.h>
#include <utils/itemviews.h>
......@@ -47,7 +49,6 @@ class IContext;
namespace Autotest {
namespace Internal {
class TestResult;
class TestResultModel;
class TestResultFilterModel;
......@@ -90,7 +91,7 @@ public:
signals:
public slots:
void addTestResult(TestResult *result);
void addTestResult(const TestResultPtr &result);
private slots:
void onItemActivated(const QModelIndex &index);
......
......@@ -90,16 +90,16 @@ TestRunner::TestRunner(QObject *parent) :
QObject(parent),
m_executingTests(false)
{
connect(&m_futureWatcher, &QFutureWatcher<TestResult *>::resultReadyAt,
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::resultReadyAt,
this, [this](int index) { emit testResultReady(m_futureWatcher.resultAt(index)); });
connect(&m_futureWatcher, &QFutureWatcher<TestResult *>::finished,
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::finished,
this, &TestRunner::onFinished);
connect(this, &TestRunner::requestStopTestRun,
&m_futureWatcher, &QFutureWatcher<TestResult *>::cancel);
connect(&m_futureWatcher, &QFutureWatcher<TestResult *>::canceled,
this, [this]() { emit testResultReady(new FaultyTestResult(
&m_futureWatcher, &QFutureWatcher<TestResultPtr>::cancel);
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::canceled,
this, [this]() { emit testResultReady(TestResultPtr(new FaultyTestResult(
Result::MessageFatal,
QObject::tr("Test run canceled by user.")));
QObject::tr("Test run canceled by user."))));
});
}
......@@ -117,7 +117,7 @@ void TestRunner::setSelectedTests(const QList<TestConfiguration *> &selected)
m_selectedTests = selected;
}
static void performTestRun(QFutureInterface<TestResult *> &futureInterface,
static void performTestRun(QFutureInterface<TestResultPtr> &futureInterface,
const QList<TestConfiguration *> selectedTests,
const TestSettings &settings)
{
......@@ -130,9 +130,9 @@ static void performTestRun(QFutureInterface<TestResult *> &futureInterface,
if (config->project()) {
testCaseCount += config->testCaseCount();
} else {
futureInterface.reportResult(new FaultyTestResult(Result::MessageWarn,
futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
QObject::tr("Project is null for \"%1\". Removing from test run.\n"
"Check the test environment.").arg(config->displayName())));
"Check the test environment.").arg(config->displayName()))));
}
}
......@@ -164,10 +164,10 @@ static void performTestRun(QFutureInterface<TestResult *> &futureInterface,
QProcessEnvironment environment = testConfiguration->environment().toProcessEnvironment();
QString commandFilePath = executableFilePath(testConfiguration->targetFile(), environment);
if (commandFilePath.isEmpty()) {
futureInterface.reportResult(new FaultyTestResult(Result::MessageFatal,
futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
QObject::tr("Could not find command \"%1\". (%2)")
.arg(testConfiguration->targetFile())
.arg(testConfiguration->displayName())));
.arg(testConfiguration->displayName()))));
continue;
}
......@@ -227,8 +227,9 @@ static void performTestRun(QFutureInterface<TestResult *> &futureInterface,
testProcess.kill();
testProcess.waitForFinished();
}
futureInterface.reportResult(new FaultyTestResult(Result::MessageFatal, QObject::tr(
"Test case canceled due to timeout. \nMaybe raise the timeout?")));
futureInterface.reportResult(TestResultPtr(
new FaultyTestResult(Result::MessageFatal, QObject::tr(
"Test case canceled due to timeout. \nMaybe raise the timeout?"))));
}
}
futureInterface.setProgressValue(testCaseCount);
......@@ -253,25 +254,25 @@ void TestRunner::prepareToRunTests()
foreach (TestConfiguration *config, m_selectedTests) {
if (!omitRunConfigWarnings && config->guessedConfiguration()) {
emit testResultReady(new FaultyTestResult(Result::MessageWarn,
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
tr("Project's run configuration was guessed for \"%1\".\n"
"This might cause trouble during execution.").arg(config->displayName())));
"This might cause trouble during execution.").arg(config->displayName()))));
}
}
if (m_selectedTests.empty()) {
emit testResultReady(new FaultyTestResult(Result::MessageWarn,
tr("No tests selected. Canceling test run.")));
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
tr("No tests selected. Canceling test run."))));
onFinished();
return;
}
ProjectExplorer::Project *project = m_selectedTests.at(0)->project();
if (!project) {
emit testResultReady(new FaultyTestResult(Result::MessageWarn,
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
tr("Project is null. Canceling test run.\n"
"Only desktop kits are supported. Make sure the "
"currently active kit is a desktop kit.")));
"currently active kit is a desktop kit."))));
onFinished();
return;
}
......@@ -282,8 +283,8 @@ void TestRunner::prepareToRunTests()
if (project->hasActiveBuildSettings()) {
buildProject(project);
} else {
emit testResultReady(new FaultyTestResult(Result::MessageFatal,
tr("Project is not configured. Canceling test run.")));
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
tr("Project is not configured. Canceling test run."))));
onFinished();
return;
}
......@@ -292,8 +293,8 @@ void TestRunner::prepareToRunTests()
void TestRunner::runTests()
{
QFuture<TestResult *> future = Utils::runAsync(&performTestRun, m_selectedTests,
*AutotestPlugin::instance()->settings());
QFuture<TestResultPtr> future = Utils::runAsync(&performTestRun, m_selectedTests,
*AutotestPlugin::instance()->settings());
m_futureWatcher.setFuture(future);
Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX);
}
......@@ -318,8 +319,8 @@ void TestRunner::buildFinished(bool success)
if (success) {
runTests();
} else {
emit testResultReady(new FaultyTestResult(Result::MessageFatal,
tr("Build failed. Canceling test run.")));
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
tr("Build failed. Canceling test run."))));
onFinished();
}
}
......
......@@ -55,7 +55,7 @@ signals:
void testRunStarted();
void testRunFinished();
void requestStopTestRun();
void testResultReady(TestResult *result);
void testResultReady(const TestResultPtr &result);
public slots:
void prepareToRunTests();
......@@ -69,7 +69,7 @@ private:
void runTests();
explicit TestRunner(QObject *parent = 0);
QFutureWatcher<TestResult *> m_futureWatcher;
QFutureWatcher<TestResultPtr> m_futureWatcher;
QList<TestConfiguration *> m_selectedTests;
bool m_executingTests;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment