Get rid of the Locker in TestResultModel...

...use signals and slots instead.

Additionally re-use the existing item that is displaying the
"Entering Test Function..." information.

Change-Id: Ibedac01ced9e987d542aa4dc878588fbec84d585
Reviewed-by: Tim Jenssen <tim.jenssen@theqtcompany.com>
This commit is contained in:
Tim Jenssen
2015-01-08 12:51:01 +01:00
committed by Christian Stenger
parent be4c06fdaf
commit ba8979d066
7 changed files with 35 additions and 42 deletions

View File

@@ -51,6 +51,8 @@ static AutotestPlugin *m_instance = 0;
AutotestPlugin::AutotestPlugin() AutotestPlugin::AutotestPlugin()
: m_settings(new TestSettings) : m_settings(new TestSettings)
{ {
// needed to be used in QueuedConnection connects
qRegisterMetaType<TestResult>();
// Create your members // Create your members
m_instance = this; m_instance = this;
} }

View File

@@ -46,7 +46,8 @@ class TestResult
{ {
public: public:
TestResult(const QString &className, const QString &testCase, const QString &dataTag = QString(), TestResult(const QString &className = QString(), const QString &testCase = QString(),
const QString &dataTag = QString(),
ResultType result = UNKNOWN, const QString &description = QString()); ResultType result = UNKNOWN, const QString &description = QString());
QString className() const { return m_class; } QString className() const { return m_class; }
@@ -57,6 +58,7 @@ public:
QString fileName() const { return m_file; } QString fileName() const { return m_file; }
int line() const { return m_line; } int line() const { return m_line; }
void setDescription(const QString &description) { m_description = description; }
void setFileName(const QString &fileName) { m_file = fileName; } void setFileName(const QString &fileName) { m_file = fileName; }
void setLine(int line) { m_line = line; } void setLine(int line) { m_line = line; }
@@ -87,6 +89,7 @@ bool operator==(const TestResult &t1, const TestResult &t2);
} // namespace Internal } // namespace Internal
} // namespace Autotest } // namespace Autotest
Q_DECLARE_METATYPE(Autotest::Internal::TestResult)
Q_DECLARE_METATYPE(Autotest::Internal::ResultType) Q_DECLARE_METATYPE(Autotest::Internal::ResultType)
#endif // TESTRESULT_H #endif // TESTRESULT_H

View File

@@ -36,7 +36,6 @@ TestResultModel::TestResultModel(QObject *parent) :
TestResultModel::~TestResultModel() TestResultModel::~TestResultModel()
{ {
QWriteLocker lock(&m_rwLock);
m_testResults.clear(); m_testResults.clear();
} }
@@ -54,7 +53,6 @@ QModelIndex TestResultModel::parent(const QModelIndex &) const
int TestResultModel::rowCount(const QModelIndex &parent) const int TestResultModel::rowCount(const QModelIndex &parent) const
{ {
QReadLocker lock(&m_rwLock);
return parent.isValid() ? 0 : m_testResults.size(); return parent.isValid() ? 0 : m_testResults.size();
} }
@@ -85,7 +83,6 @@ static QIcon testResultIcon(ResultType result) {
QVariant TestResultModel::data(const QModelIndex &index, int role) const QVariant TestResultModel::data(const QModelIndex &index, int role) const
{ {
QReadLocker lock(&m_rwLock);
if (!index.isValid() || index.row() >= m_testResults.count() || index.column() != 0) if (!index.isValid() || index.row() >= m_testResults.count() || index.column() != 0)
return QVariant(); return QVariant();
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
@@ -118,23 +115,17 @@ void TestResultModel::addTestResult(const TestResult &testResult)
const bool isCurrentTestMssg = testResult.result() == ResultType::MESSAGE_CURRENT_TEST; const bool isCurrentTestMssg = testResult.result() == ResultType::MESSAGE_CURRENT_TEST;
const bool hasCurrentTestMssg = m_availableResultTypes.contains(ResultType::MESSAGE_CURRENT_TEST); const bool hasCurrentTestMssg = m_availableResultTypes.contains(ResultType::MESSAGE_CURRENT_TEST);
QReadLocker rLock(&m_rwLock);
int position = m_testResults.size(); int position = m_testResults.size();
rLock.unlock();
if (hasCurrentTestMssg && isCurrentTestMssg) { if (hasCurrentTestMssg && isCurrentTestMssg) {
beginRemoveRows(QModelIndex(), position, position); m_testResults.last().setDescription(testResult.description());
QWriteLocker wLock(&m_rwLock); const QModelIndex changed = index(m_testResults.size() - 1, 0, QModelIndex());
m_testResults.replace(position - 1, testResult); emit dataChanged(changed, changed);
wLock.unlock();
endRemoveRows();
} else { } else {
if (!isCurrentTestMssg && position) // decrement only if at least one other item if (!isCurrentTestMssg && position) // decrement only if at least one other item
--position; --position;
beginInsertRows(QModelIndex(), position, position); beginInsertRows(QModelIndex(), position, position);
QWriteLocker wLock(&m_rwLock);
m_testResults.insert(position, testResult); m_testResults.insert(position, testResult);
wLock.unlock();
endInsertRows(); endInsertRows();
} }
@@ -148,13 +139,9 @@ void TestResultModel::addTestResult(const TestResult &testResult)
void TestResultModel::removeCurrentTestMessage() void TestResultModel::removeCurrentTestMessage()
{ {
QReadLocker rLock(&m_rwLock);
if (m_availableResultTypes.contains(ResultType::MESSAGE_CURRENT_TEST)) { if (m_availableResultTypes.contains(ResultType::MESSAGE_CURRENT_TEST)) {
beginRemoveRows(QModelIndex(), m_testResults.size() - 1, m_testResults.size() - 1); beginRemoveRows(QModelIndex(), m_testResults.size() - 1, m_testResults.size() - 1);
rLock.unlock();
QWriteLocker wLock(&m_rwLock);
m_testResults.removeLast(); m_testResults.removeLast();
wLock.unlock();
endRemoveRows(); endRemoveRows();
m_availableResultTypes.remove(ResultType::MESSAGE_CURRENT_TEST); m_availableResultTypes.remove(ResultType::MESSAGE_CURRENT_TEST);
} }
@@ -162,14 +149,10 @@ void TestResultModel::removeCurrentTestMessage()
void TestResultModel::clearTestResults() void TestResultModel::clearTestResults()
{ {
QReadLocker rLock(&m_rwLock);
if (m_testResults.size() == 0) if (m_testResults.size() == 0)
return; return;
beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1); beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1);
rLock.unlock();
QWriteLocker wLock(&m_rwLock);
m_testResults.clear(); m_testResults.clear();
wLock.unlock();
m_testResultCount.clear(); m_testResultCount.clear();
m_lastMaxWidthIndex = 0; m_lastMaxWidthIndex = 0;
m_maxWidthOfFileName = 0; m_maxWidthOfFileName = 0;
@@ -182,15 +165,12 @@ TestResult TestResultModel::testResult(const QModelIndex &index) const
{ {
if (!index.isValid()) if (!index.isValid())
return TestResult(QString(), QString()); return TestResult(QString(), QString());
QReadLocker lock(&m_rwLock);
return m_testResults.at(index.row()); return m_testResults.at(index.row());
} }
int TestResultModel::maxWidthOfFileName(const QFont &font) int TestResultModel::maxWidthOfFileName(const QFont &font)
{ {
QReadLocker lock(&m_rwLock);
int count = m_testResults.size(); int count = m_testResults.size();
lock.unlock();
if (count == 0) if (count == 0)
return 0; return 0;
if (m_maxWidthOfFileName > 0 && font == m_measurementFont && m_lastMaxWidthIndex == count - 1) if (m_maxWidthOfFileName > 0 && font == m_measurementFont && m_lastMaxWidthIndex == count - 1)
@@ -200,9 +180,7 @@ int TestResultModel::maxWidthOfFileName(const QFont &font)
m_measurementFont = font; m_measurementFont = font;
for (int i = m_lastMaxWidthIndex; i < count; ++i) { for (int i = m_lastMaxWidthIndex; i < count; ++i) {
lock.relock();
QString filename = m_testResults.at(i).fileName(); QString filename = m_testResults.at(i).fileName();
lock.unlock();
const int pos = filename.lastIndexOf(QLatin1Char('/')); const int pos = filename.lastIndexOf(QLatin1Char('/'));
if (pos != -1) if (pos != -1)
filename = filename.mid(pos +1); filename = filename.mid(pos +1);

View File

@@ -24,7 +24,6 @@
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <QFont> #include <QFont>
#include <QReadWriteLock>
#include <QSet> #include <QSet>
namespace Autotest { namespace Autotest {
@@ -67,7 +66,6 @@ private:
int m_lastMaxWidthIndex; int m_lastMaxWidthIndex;
QFont m_measurementFont; QFont m_measurementFont;
QSet<ResultType> m_availableResultTypes; QSet<ResultType> m_availableResultTypes;
mutable QReadWriteLock m_rwLock;
}; };
class TestResultFilterModel : public QSortFilterProxyModel class TestResultFilterModel : public QSortFilterProxyModel

View File

@@ -52,8 +52,6 @@ public:
virtual ~TestResultsPane(); virtual ~TestResultsPane();
static TestResultsPane *instance(); static TestResultsPane *instance();
void addTestResult(const TestResult &result);
// IOutputPane interface // IOutputPane interface
QWidget *outputWidget(QWidget *parent); QWidget *outputWidget(QWidget *parent);
QList<QWidget *> toolBarWidgets() const; QList<QWidget *> toolBarWidgets() const;
@@ -73,6 +71,7 @@ public:
signals: signals:
public slots: public slots:
void addTestResult(const TestResult &result);
private slots: private slots:
void onItemActivated(const QModelIndex &index); void onItemActivated(const QModelIndex &index);

View File

@@ -192,6 +192,11 @@ static bool xmlExtractBenchmarkInformation(const QString &code, const QString &t
return false; return false;
} }
void emitTestResultCreated(const TestResult &testResult)
{
emit m_instance->testResultCreated(testResult);
}
/****************** XML line parser helper end ******************/ /****************** XML line parser helper end ******************/
void processOutput() void processOutput()
@@ -228,8 +233,8 @@ void processOutput()
result = ResultType::UNKNOWN; result = ResultType::UNKNOWN;
lineNumber = 0; lineNumber = 0;
readingDescription = false; readingDescription = false;
TestResultsPane::instance()->addTestResult( emitTestResultCreated(
TestResult(className, testCase, QString(), ResultType::MESSAGE_CURRENT_TEST, TestResult(QString(), QString(), QString(), ResultType::MESSAGE_CURRENT_TEST,
QObject::tr("Entering Test Function %1::%2") QObject::tr("Entering Test Function %1::%2")
.arg(className).arg(testCase))); .arg(className).arg(testCase)));
continue; continue;
@@ -253,13 +258,13 @@ void processOutput()
file = QFileInfo(m_runner->workingDirectory(), file).canonicalFilePath(); file = QFileInfo(m_runner->workingDirectory(), file).canonicalFilePath();
testResult.setFileName(file); testResult.setFileName(file);
testResult.setLine(lineNumber); testResult.setLine(lineNumber);
TestResultsPane::instance()->addTestResult(testResult); emitTestResultCreated(testResult);
} }
continue; continue;
} }
if (xmlExtractBenchmarkInformation(line, QLatin1String("<BenchmarkResult"), bmDescription)) { if (xmlExtractBenchmarkInformation(line, QLatin1String("<BenchmarkResult"), bmDescription)) {
TestResult testResult(className, testCase, dataTag, ResultType::BENCHMARK, bmDescription); TestResult testResult(className, testCase, dataTag, ResultType::BENCHMARK, bmDescription);
TestResultsPane::instance()->addTestResult(testResult); emitTestResultCreated(testResult);
continue; continue;
} }
if (line == QLatin1String("</Message>") || line == QLatin1String("</Incident>")) { if (line == QLatin1String("</Message>") || line == QLatin1String("</Incident>")) {
@@ -268,17 +273,17 @@ void processOutput()
file = QFileInfo(m_runner->workingDirectory(), file).canonicalFilePath(); file = QFileInfo(m_runner->workingDirectory(), file).canonicalFilePath();
testResult.setFileName(file); testResult.setFileName(file);
testResult.setLine(lineNumber); testResult.setLine(lineNumber);
TestResultsPane::instance()->addTestResult(testResult); emitTestResultCreated(testResult);
description = QString(); description = QString();
} else if (line == QLatin1String("</TestFunction>") && !duration.isEmpty()) { } else if (line == QLatin1String("</TestFunction>") && !duration.isEmpty()) {
TestResult testResult(className, testCase, QString(), ResultType::MESSAGE_INTERNAL, TestResult testResult(className, testCase, QString(), ResultType::MESSAGE_INTERNAL,
QObject::tr("execution took %1ms").arg(duration)); QObject::tr("execution took %1ms").arg(duration));
TestResultsPane::instance()->addTestResult(testResult); emitTestResultCreated(testResult);
m_currentFuture->setProgressValue(m_currentFuture->progressValue() + 1); m_currentFuture->setProgressValue(m_currentFuture->progressValue() + 1);
} else if (line == QLatin1String("</TestCase>") && !duration.isEmpty()) { } else if (line == QLatin1String("</TestCase>") && !duration.isEmpty()) {
TestResult testResult(className, QString(), QString(), ResultType::MESSAGE_INTERNAL, TestResult testResult(className, QString(), QString(), ResultType::MESSAGE_INTERNAL,
QObject::tr("Test execution took %1ms").arg(duration)); QObject::tr("Test execution took %1ms").arg(duration));
TestResultsPane::instance()->addTestResult(testResult); emitTestResultCreated(testResult);
} else if (readingDescription) { } else if (readingDescription) {
if (line.endsWith(QLatin1String("]]></Description>"))) { if (line.endsWith(QLatin1String("]]></Description>"))) {
description.append(QLatin1Char('\n')); description.append(QLatin1Char('\n'));
@@ -289,10 +294,10 @@ void processOutput()
description.append(line); description.append(line);
} }
} else if (xmlStartsWith(line, QLatin1String("<QtVersion>"), qtVersion)) { } else if (xmlStartsWith(line, QLatin1String("<QtVersion>"), qtVersion)) {
TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_INTERNAL, emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_INTERNAL,
QObject::tr("Qt Version: %1").arg(qtVersion))); QObject::tr("Qt Version: %1").arg(qtVersion)));
} else if (xmlStartsWith(line, QLatin1String("<QTestVersion>"), qtestVersion)) { } else if (xmlStartsWith(line, QLatin1String("<QTestVersion>"), qtestVersion)) {
TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_INTERNAL, emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_INTERNAL,
QObject::tr("QTest Version: %1").arg(qtestVersion))); QObject::tr("QTest Version: %1").arg(qtestVersion)));
} else { } else {
// qDebug() << "Unhandled line:" << line; // TODO remove // qDebug() << "Unhandled line:" << line; // TODO remove
@@ -344,7 +349,7 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor
} }
if (runCmd.isEmpty()) { if (runCmd.isEmpty()) {
TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_FATAL,
QObject::tr("*** Could not find command '%1' ***").arg(cmd))); QObject::tr("*** Could not find command '%1' ***").arg(cmd)));
return false; return false;
} }
@@ -366,7 +371,7 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor
if (m_currentFuture->isCanceled()) { if (m_currentFuture->isCanceled()) {
m_runner->kill(); m_runner->kill();
m_runner->waitForFinished(); m_runner->waitForFinished();
TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_FATAL,
QObject::tr("*** Test Run canceled by user ***"))); QObject::tr("*** Test Run canceled by user ***")));
} }
qApp->processEvents(); qApp->processEvents();
@@ -378,7 +383,7 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor
if (m_runner->state() != QProcess::NotRunning) { if (m_runner->state() != QProcess::NotRunning) {
m_runner->kill(); m_runner->kill();
m_runner->waitForFinished(); m_runner->waitForFinished();
TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_FATAL,
QObject::tr("*** Test Case canceled due to timeout ***\nMaybe raise the timeout?"))); QObject::tr("*** Test Case canceled due to timeout ***\nMaybe raise the timeout?")));
} }
return false; return false;
@@ -484,6 +489,10 @@ void TestRunner::runTests()
} }
m_executingTests = true; m_executingTests = true;
connect(this, &TestRunner::testResultCreated,
TestResultsPane::instance(), &TestResultsPane::addTestResult,
Qt::QueuedConnection);
emit testRunStarted(); emit testRunStarted();
QFuture<void> future = QtConcurrent::run(&performTestRun , m_selectedTests); QFuture<void> future = QtConcurrent::run(&performTestRun , m_selectedTests);
Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"),
@@ -516,6 +525,9 @@ void TestRunner::buildFinished(bool success)
void TestRunner::onFinished() void TestRunner::onFinished()
{ {
disconnect(this, &TestRunner::testResultCreated,
TestResultsPane::instance(), &TestResultsPane::addTestResult);
m_executingTests = false; m_executingTests = false;
emit testRunFinished(); emit testRunFinished();
} }

View File

@@ -46,6 +46,7 @@ public:
signals: signals:
void testRunStarted(); void testRunStarted();
void testRunFinished(); void testRunFinished();
void testResultCreated(const TestResult &testResult);
public slots: public slots:
void runTests(); void runTests();