diff --git a/src/plugins/autotest/qtest/qttestframework.cpp b/src/plugins/autotest/qtest/qttestframework.cpp index 0f854ab6f59..009acc81ab1 100644 --- a/src/plugins/autotest/qtest/qttestframework.cpp +++ b/src/plugins/autotest/qtest/qttestframework.cpp @@ -44,7 +44,8 @@ QtTestFramework::QtTestFramework() title(Tr::tr("Benchmark Metrics")), Column { metrics } }, br, - quickCheckForDerivedTests, br + quickCheckForDerivedTests, br, + parseMessages, br }, st }; }); @@ -100,6 +101,15 @@ QtTestFramework::QtTestFramework() Tr::tr("Search for Qt Quick tests that are derived from TestCase.\nWarning: Enabling this " "feature significantly increases scan time.")); + parseMessages.setSettingsKey("ParseMessages"); + parseMessages.setDefaultValue(false); + parseMessages.setLabelText(Tr::tr("Find user-defined locations")); + parseMessages.setToolTip( + Tr::tr("Parse messages for the pattern \"file://filepath:line\", where \":line\" is " + "optional, and use this as location information.\n" + "Warning: If the patterns are used in code, the location information for debug " + "messages and other messages might improve,\n" + "at the risk of some incorrect locations and lower performance.")); readSettings(); maxWarnings.setEnabler(&limitWarnings); diff --git a/src/plugins/autotest/qtest/qttestframework.h b/src/plugins/autotest/qtest/qttestframework.h index 47bf454484e..0e175694582 100644 --- a/src/plugins/autotest/qtest/qttestframework.h +++ b/src/plugins/autotest/qtest/qttestframework.h @@ -31,6 +31,7 @@ public: Utils::BoolAspect limitWarnings{this}; Utils::IntegerAspect maxWarnings{this}; Utils::BoolAspect quickCheckForDerivedTests{this}; + Utils::BoolAspect parseMessages{this}; QStringList testNameForSymbolName(const QString &symbolName) const override; diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp index 1d1b1503818..b668ea442f6 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.cpp +++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp @@ -4,6 +4,7 @@ #include "qttestoutputreader.h" #include "qttestresult.h" +#include "qttestframework.h" #include "../autotesttr.h" #include "../testtreeitem.h" @@ -17,6 +18,12 @@ using namespace Utils; namespace Autotest { namespace Internal { +static QRegularExpression userFileLocation() +{ + static const QRegularExpression regex("^.*\\bfile://((?\\S+))(:(?\\d+))\\b.*$", + QRegularExpression::DotMatchesEverythingOption); + return regex; +} static QString decode(const QString& original) { QString result(original); @@ -110,6 +117,7 @@ QtTestOutputReader::QtTestOutputReader(Process *testApplication, , m_mode(mode) , m_testType(type) { + m_parseMessages = theQtTestFramework().parseMessages(); } void QtTestOutputReader::processOutputLine(const QByteArray &outputLine) @@ -277,6 +285,14 @@ void QtTestOutputReader::processXMLOutput(const QByteArray &outputLine) } else if (currentTag == QStringLiteral("TestCase")) { sendFinishMessage(false); } else if (validEndTags.contains(currentTag.toString())) { + if (m_parseMessages && isTestMessage(m_result)) { + const QRegularExpressionMatch match = userFileLocation().match(m_description); + if (match.hasMatch()) { + // we need to handle possible automatic masking done by qDebug() + processLocationOutput(match.captured("file").replace("\\\\", "\\"), + match.captured("line")); + } + } sendCompleteInformation(); if (currentTag == QStringLiteral("Incident")) m_dataTag.clear(); @@ -350,6 +366,11 @@ void QtTestOutputReader::processPlainTextOutput(const QByteArray &outputLine) if (hasMatch(result)) { processResultOutput(match.captured(1).toLower().trimmed(), match.captured(2)); + if (m_parseMessages && isTestMessage(m_result) && hasMatch(userFileLocation())) { + // we need to handle possible automatic masking done by qDebug() + processLocationOutput(match.captured("file").replace("\\\\", "\\"), + match.captured("line")); + } } else if (hasMatch(locationUnix)) { processLocationOutput(match.captured("file"), match.captured("line")); } else if (hasMatch(locationWin)) { @@ -416,7 +437,7 @@ void QtTestOutputReader::processLocationOutput(const QStringView file, const QSt { QTC_ASSERT(!file.isEmpty(), return); m_file = constructSourceFilePath(m_buildDir, file.toString()); - m_lineNumber = line.toInt(); + m_lineNumber = m_file.isEmpty() ? 0 : line.toInt(); } void QtTestOutputReader::processSummaryFinishOutput() diff --git a/src/plugins/autotest/qtest/qttestoutputreader.h b/src/plugins/autotest/qtest/qttestoutputreader.h index d09f3d56116..75c2e0b57aa 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.h +++ b/src/plugins/autotest/qtest/qttestoutputreader.h @@ -66,6 +66,7 @@ private: QXmlStreamReader m_xmlReader; OutputMode m_mode = XML; TestType m_testType = TestType::QtTest; + bool m_parseMessages = false; bool m_expectTag = true; }; diff --git a/src/plugins/autotest/testresult.h b/src/plugins/autotest/testresult.h index 80229d37362..0f193eb3558 100644 --- a/src/plugins/autotest/testresult.h +++ b/src/plugins/autotest/testresult.h @@ -52,6 +52,11 @@ enum class ResultType { LAST_TYPE = Invalid }; +static inline bool isTestMessage(const ResultType &result) +{ + return result >= ResultType::MessageDebug && result <= ResultType::MessageError; +} + inline auto qHash(const ResultType &result) { return QT_PREPEND_NAMESPACE(qHash(int(result)));