diff --git a/src/plugins/autotest/boost/boosttestoutputreader.cpp b/src/plugins/autotest/boost/boosttestoutputreader.cpp index 927b8a4863f..9cd2d6c1685 100644 --- a/src/plugins/autotest/boost/boosttestoutputreader.cpp +++ b/src/plugins/autotest/boost/boosttestoutputreader.cpp @@ -74,9 +74,8 @@ static QString caseFromContent(const QString &content) void BoostTestOutputReader::sendCompleteInformation() { QTC_ASSERT(m_result != ResultType::Invalid, return); - BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule); - result->setTestSuite(m_currentSuite); - result->setTestCase(m_currentTest); + BoostTestResult *result = new BoostTestResult(id(), m_currentModule, m_projectFile, + m_currentTest, m_currentSuite); if (m_lineNumber) { result->setLine(m_lineNumber); result->setFileName(m_fileName); @@ -213,7 +212,7 @@ void BoostTestOutputReader::processOutputLine(const QByteArray &outputLine) if (match.hasMatch()) { if (m_result != ResultType::Invalid) sendCompleteInformation(); - BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule); + BoostTestResult *result = new BoostTestResult(id(), m_currentModule, m_projectFile); result->setDescription(match.captured(0)); result->setResult(ResultType::MessageInfo); reportResult(TestResultPtr(result)); @@ -235,14 +234,14 @@ void BoostTestOutputReader::processOutputLine(const QByteArray &outputLine) sendCompleteInformation(); if (match.captured(1).startsWith("Entering")) { m_currentModule = match.captured(2); - BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule); + BoostTestResult *result = new BoostTestResult(id(), m_currentModule, m_projectFile); result->setDescription(Tr::tr("Executing test module %1").arg(m_currentModule)); result->setResult(ResultType::TestStart); reportResult(TestResultPtr(result)); m_description.clear(); } else { QTC_CHECK(m_currentModule == match.captured(3)); - BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule); + BoostTestResult *result = new BoostTestResult(id(), m_currentModule, m_projectFile); result->setDescription(Tr::tr("Test module execution took %1").arg(match.captured(4))); result->setResult(ResultType::TestEnd); reportResult(TestResultPtr(result)); @@ -326,7 +325,7 @@ void BoostTestOutputReader::processOutputLine(const QByteArray &outputLine) if (match.hasMatch()) { if (m_result != ResultType::Invalid) sendCompleteInformation(); - BoostTestResult *result = new BoostTestResult(id(), m_projectFile, QString()); + BoostTestResult *result = new BoostTestResult(id(), {}, m_projectFile); int failed = match.captured(1).toInt(); int fatals = m_summary.value(ResultType::MessageFatal); QString txt = Tr::tr("%1 failures detected in %2.").arg(failed).arg(match.captured(3)); @@ -347,7 +346,7 @@ void BoostTestOutputReader::processOutputLine(const QByteArray &outputLine) if (line == noErrors) { if (m_result != ResultType::Invalid) sendCompleteInformation(); - BoostTestResult *result = new BoostTestResult(id(), m_projectFile, QString()); + BoostTestResult *result = new BoostTestResult(id(), {}, m_projectFile); QString txt = Tr::tr("No errors detected."); if (m_testCaseCount != -1) txt.append(' ').append(Tr::tr("%1 tests passed.").arg(m_testCaseCount)); @@ -375,11 +374,8 @@ void BoostTestOutputReader::processStdError(const QByteArray &outputLine) TestResultPtr BoostTestOutputReader::createDefaultResult() const { - BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule); - result->setTestSuite(m_currentSuite); - result->setTestCase(m_currentTest); - - return TestResultPtr(result); + return TestResultPtr(new BoostTestResult(id(), m_currentModule, m_projectFile, + m_currentTest, m_currentSuite)); } void BoostTestOutputReader::onDone() { @@ -420,8 +416,8 @@ void BoostTestOutputReader::onDone() { void BoostTestOutputReader::reportNoOutputFinish(const QString &description, ResultType type) { - BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule); - result->setTestCase(Tr::tr("Running tests without output.")); + BoostTestResult *result = new BoostTestResult(id(), m_currentModule, m_projectFile, + Tr::tr("Running tests without output.")); result->setDescription(description); result->setResult(type); reportResult(TestResultPtr(result)); diff --git a/src/plugins/autotest/boost/boosttestoutputreader.h b/src/plugins/autotest/boost/boosttestoutputreader.h index 2943de8daaf..74cc82271d9 100644 --- a/src/plugins/autotest/boost/boosttestoutputreader.h +++ b/src/plugins/autotest/boost/boosttestoutputreader.h @@ -8,7 +8,6 @@ namespace Autotest { namespace Internal { -class BoostTestResult; enum class LogLevel; enum class ReportLevel; diff --git a/src/plugins/autotest/boost/boosttestresult.cpp b/src/plugins/autotest/boost/boosttestresult.cpp index 8cd902a95c1..aa7a991eb56 100644 --- a/src/plugins/autotest/boost/boosttestresult.cpp +++ b/src/plugins/autotest/boost/boosttestresult.cpp @@ -14,28 +14,35 @@ namespace Autotest { namespace Internal { -BoostTestResult::BoostTestResult(const QString &id, const Utils::FilePath &projectFile, const QString &name) - : TestResult(id, name), m_projectFile(projectFile) +static ResultHooks::OutputStringHook outputStringHook(const QString &testCaseName) { + return [testCaseName](const TestResult &result, bool selected) { + const QString &desc = result.description(); + QString output; + switch (result.result()) { + case ResultType::Pass: + case ResultType::Fail: + output = testCaseName; + if (selected && !desc.isEmpty()) + output.append('\n').append(desc); + break; + default: + output = desc; + if (!selected) + output = output.split('\n').first(); + } + return output; + }; } -const QString BoostTestResult::outputString(bool selected) const +BoostTestResult::BoostTestResult(const QString &id, const QString &name, + const Utils::FilePath &projectFile, + const QString &testCaseName, const QString &testSuiteName) + : TestResult(id, name, {outputStringHook(testCaseName)}) + , m_projectFile(projectFile) + , m_testCaseName(testCaseName) + , m_testSuiteName(testSuiteName) { - const QString &desc = description(); - QString output; - switch (result()) { - case ResultType::Pass: - case ResultType::Fail: - output = m_testCase; - if (selected && !desc.isEmpty()) - output.append('\n').append(desc); - break; - default: - output = desc; - if (!selected) - output = output.split('\n').first(); - } - return output; } bool BoostTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermediate) const @@ -46,24 +53,24 @@ bool BoostTestResult::isDirectParentOf(const TestResult *other, bool *needsInter if (result() != ResultType::TestStart) return false; - bool weAreModule = (m_testCase.isEmpty() && m_testSuite.isEmpty()); - bool weAreSuite = (m_testCase.isEmpty() && !m_testSuite.isEmpty()); - bool weAreCase = (!m_testCase.isEmpty()); + bool weAreModule = (m_testCaseName.isEmpty() && m_testSuiteName.isEmpty()); + bool weAreSuite = (m_testCaseName.isEmpty() && !m_testSuiteName.isEmpty()); + bool weAreCase = (!m_testCaseName.isEmpty()); const BoostTestResult *boostOther = static_cast(other); - bool otherIsSuite = boostOther->m_testCase.isEmpty() && !boostOther->m_testSuite.isEmpty(); - bool otherIsCase = !boostOther->m_testCase.isEmpty(); + bool otherIsSuite = boostOther->m_testCaseName.isEmpty() && !boostOther->m_testSuiteName.isEmpty(); + bool otherIsCase = !boostOther->m_testCaseName.isEmpty(); if (otherIsSuite) - return weAreSuite ? boostOther->m_testSuite.startsWith(m_testSuite + '/') : weAreModule; + return weAreSuite ? boostOther->m_testSuiteName.startsWith(m_testSuiteName + '/') : weAreModule; if (otherIsCase) { if (weAreCase) - return boostOther->m_testCase == m_testCase && boostOther->m_testSuite == m_testSuite; + return boostOther->m_testCaseName == m_testCaseName && boostOther->m_testSuiteName == m_testSuiteName; if (weAreSuite) - return boostOther->m_testSuite == m_testSuite; + return boostOther->m_testSuiteName == m_testSuiteName; if (weAreModule) - return boostOther->m_testSuite.isEmpty(); + return boostOther->m_testSuiteName.isEmpty(); } return false; } @@ -88,16 +95,16 @@ bool BoostTestResult::matches(const BoostTestTreeItem *item) const // might end up here with a differing set of tests, but it's the best we can do if (!item) return false; - if (m_testCase.isEmpty()) // a top level module node + if (m_testCaseName.isEmpty()) // a top level module node return item->proFile() == m_projectFile; if (item->proFile() != m_projectFile) return false; if (!fileName().isEmpty() && fileName() != item->filePath()) return false; - QString fullName = "::" + m_testCase; - fullName.prepend(m_testSuite.isEmpty() ? QString(BoostTest::Constants::BOOST_MASTER_SUITE) - : m_testSuite); + QString fullName = "::" + m_testCaseName; + fullName.prepend(m_testSuiteName.isEmpty() ? QString(BoostTest::Constants::BOOST_MASTER_SUITE) + : m_testSuiteName); BoostTestTreeItem::TestStates states = item->state(); if (states & BoostTestTreeItem::Templated) { diff --git a/src/plugins/autotest/boost/boosttestresult.h b/src/plugins/autotest/boost/boosttestresult.h index 1543e84a15b..7ea2be62dd8 100644 --- a/src/plugins/autotest/boost/boosttestresult.h +++ b/src/plugins/autotest/boost/boosttestresult.h @@ -13,19 +13,17 @@ class BoostTestTreeItem; class BoostTestResult : public TestResult { public: - BoostTestResult(const QString &id, const Utils::FilePath &projectFile, const QString &name); - const QString outputString(bool selected) const override; + BoostTestResult(const QString &id, const QString &name, const Utils::FilePath &projectFile, + const QString &testCaseName = {}, const QString &testSuiteName = {}); bool isDirectParentOf(const TestResult *other, bool *needsIntermediate) const override; const ITestTreeItem * findTestTreeItem() const override; - void setTestSuite(const QString &testSuite) { m_testSuite = testSuite; } - void setTestCase(const QString &testCase) { m_testCase = testCase; } private: bool matches(const BoostTestTreeItem *item) const; Utils::FilePath m_projectFile; - QString m_testSuite; - QString m_testCase; + QString m_testCaseName; + QString m_testSuiteName; }; } // namespace Internal diff --git a/src/plugins/autotest/gtest/gtestoutputreader.cpp b/src/plugins/autotest/gtest/gtestoutputreader.cpp index 49ddb6b6758..19d977e1af0 100644 --- a/src/plugins/autotest/gtest/gtestoutputreader.cpp +++ b/src/plugins/autotest/gtest/gtestoutputreader.cpp @@ -70,7 +70,7 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLine) m_description = line; if (m_iteration > 1) m_description.append(' ' + Tr::tr("(iteration %1)").arg(m_iteration)); - TestResultPtr testResult = TestResultPtr(new GTestResult(id(), m_projectFile, QString())); + TestResultPtr testResult = TestResultPtr(new GTestResult(id(), {}, m_projectFile)); testResult->setResult(ResultType::MessageInternal); testResult->setDescription(m_description); reportResult(testResult); @@ -103,8 +103,7 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLine) } else if (ExactMatch match = newTestSetStarts.match(line)) { m_testSetStarted = true; setCurrentTestCase(match.captured(1)); - TestResultPtr testResult = TestResultPtr(new GTestResult(QString(), m_projectFile, - QString())); + TestResultPtr testResult = TestResultPtr(new GTestResult({}, {}, m_projectFile)); testResult->setResult(ResultType::MessageCurrentTest); testResult->setDescription(Tr::tr("Entering test case %1").arg(m_currentTestCase)); reportResult(testResult); @@ -178,9 +177,8 @@ void GTestOutputReader::processStdError(const QByteArray &outputLine) TestResultPtr GTestOutputReader::createDefaultResult() const { - GTestResult *result = new GTestResult(id(), m_projectFile, m_currentTestSuite); - result->setTestCaseName(m_currentTestCase); - result->setIteration(m_iteration); + GTestResult *result = new GTestResult(id(), m_currentTestSuite, m_projectFile, + m_currentTestCase, m_iteration); const ITestTreeItem *testItem = result->findTestTreeItem(); diff --git a/src/plugins/autotest/gtest/gtestresult.cpp b/src/plugins/autotest/gtest/gtestresult.cpp index dfa8a25d240..a83462ae144 100644 --- a/src/plugins/autotest/gtest/gtestresult.cpp +++ b/src/plugins/autotest/gtest/gtestresult.cpp @@ -14,29 +14,34 @@ namespace Autotest { namespace Internal { -GTestResult::GTestResult(const QString &id, const Utils::FilePath &projectFile, - const QString &name) - : TestResult(id, name), m_projectFile(projectFile) +static ResultHooks::OutputStringHook outputStringHook(const QString &testCaseName) { + return [testCaseName](const TestResult &result, bool selected) { + const QString &desc = result.description(); + QString output; + switch (result.result()) { + case ResultType::Pass: + case ResultType::Fail: + output = testCaseName; + if (selected && !desc.isEmpty()) + output.append('\n').append(desc); + break; + default: + output = desc; + if (!selected) + output = output.split('\n').first(); + } + return output; + }; } -const QString GTestResult::outputString(bool selected) const +GTestResult::GTestResult(const QString &id, const QString &name, const Utils::FilePath &projectFile, + const QString &testCaseName, int iteration) + : TestResult(id, name, {outputStringHook(testCaseName)}) + , m_projectFile(projectFile) + , m_testCaseName(testCaseName) + , m_iteration(iteration) { - const QString &desc = description(); - QString output; - switch (result()) { - case ResultType::Pass: - case ResultType::Fail: - output = m_testCaseName; - if (selected && !desc.isEmpty()) - output.append('\n').append(desc); - break; - default: - output = desc; - if (!selected) - output = output.split('\n').first(); - } - return output; } bool GTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermediate) const diff --git a/src/plugins/autotest/gtest/gtestresult.h b/src/plugins/autotest/gtest/gtestresult.h index cbded3b4af3..5ce8255855d 100644 --- a/src/plugins/autotest/gtest/gtestresult.h +++ b/src/plugins/autotest/gtest/gtestresult.h @@ -14,11 +14,9 @@ namespace Internal { class GTestResult : public TestResult { public: - GTestResult(const QString &id, const Utils::FilePath &projectFile, const QString &name); - const QString outputString(bool selected) const override; + GTestResult(const QString &id, const QString &name, const Utils::FilePath &projectFile, + const QString &testCaseName = {}, int iteration = 1); - void setTestCaseName(const QString &testSetName) { m_testCaseName = testSetName; } - void setIteration(int iteration) { m_iteration = iteration; } bool isDirectParentOf(const TestResult *other, bool *needsIntermediate) const override; virtual const ITestTreeItem *findTestTreeItem() const override; @@ -30,8 +28,8 @@ private: bool matchesTestCase(const TestTreeItem *treeItem) const; bool matchesTestSuite(const TestTreeItem *treeItem) const; - QString m_testCaseName; Utils::FilePath m_projectFile; + QString m_testCaseName; int m_iteration = 1; }; diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp index 1a4e628c52d..c2d06042bdd 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.cpp +++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp @@ -132,9 +132,8 @@ void QtTestOutputReader::processOutputLine(const QByteArray &outputLine) TestResultPtr QtTestOutputReader::createDefaultResult() const { - QtTestResult *result = new QtTestResult(id(), m_projectFile, m_testType, m_className); - result->setFunctionName(m_testCase); - result->setDataTag(m_dataTag); + QtTestResult *result = new QtTestResult(id(), m_className, m_projectFile, m_testType, + m_testCase, m_dataTag); return TestResultPtr(result); } @@ -475,7 +474,7 @@ void QtTestOutputReader::sendCompleteInformation() void QtTestOutputReader::sendMessageCurrentTest() { - QtTestResult *testResult = new QtTestResult(QString(), m_projectFile, m_testType, QString()); + QtTestResult *testResult = new QtTestResult({}, {}, m_projectFile, m_testType); testResult->setResult(ResultType::MessageCurrentTest); testResult->setDescription(Tr::tr("Entering test function %1::%2").arg(m_className, m_testCase)); reportResult(TestResultPtr(testResult)); diff --git a/src/plugins/autotest/qtest/qttestresult.cpp b/src/plugins/autotest/qtest/qttestresult.cpp index 1c070c908e7..bcff35c5462 100644 --- a/src/plugins/autotest/qtest/qttestresult.cpp +++ b/src/plugins/autotest/qtest/qttestresult.cpp @@ -12,53 +12,58 @@ namespace Autotest { namespace Internal { -QtTestResult::QtTestResult(const QString &id, const Utils::FilePath &projectFile, TestType type, - const QString &className) - : TestResult(id, className), m_projectFile(projectFile), m_type(type) +static ResultHooks::OutputStringHook outputStringHook(const QString &function, const QString &dataTag) { + return [function, dataTag](const TestResult &result, bool selected) { + const QString &desc = result.description(); + const QString &className = result.name(); + QString output; + switch (result.result()) { + case ResultType::Pass: + case ResultType::Fail: + case ResultType::ExpectedFail: + case ResultType::UnexpectedPass: + case ResultType::BlacklistedFail: + case ResultType::BlacklistedPass: + output = className; + if (!function.isEmpty()) + output.append("::" + function); + if (!dataTag.isEmpty()) + output.append(QString(" (%1)").arg(dataTag)); + if (selected && !desc.isEmpty()) { + output.append('\n').append(desc); + } + break; + case ResultType::Benchmark: + output = className; + if (!function.isEmpty()) + output.append("::" + function); + if (!dataTag.isEmpty()) + output.append(QString(" (%1)").arg(dataTag)); + if (!desc.isEmpty()) { + int breakPos = desc.indexOf('('); + output.append(": ").append(desc.left(breakPos)); + if (selected) + output.append('\n').append(desc.mid(breakPos)); + } + break; + default: + output = desc; + if (!selected) + output = output.split('\n').first(); + } + return output; + }; } -const QString QtTestResult::outputString(bool selected) const -{ - const QString &desc = description(); - const QString &className = name(); - QString output; - switch (result()) { - case ResultType::Pass: - case ResultType::Fail: - case ResultType::ExpectedFail: - case ResultType::UnexpectedPass: - case ResultType::BlacklistedFail: - case ResultType::BlacklistedPass: - output = className; - if (!m_function.isEmpty()) - output.append("::" + m_function); - if (!m_dataTag.isEmpty()) - output.append(QString(" (%1)").arg(m_dataTag)); - if (selected && !desc.isEmpty()) { - output.append('\n').append(desc); - } - break; - case ResultType::Benchmark: - output = className; - if (!m_function.isEmpty()) - output.append("::" + m_function); - if (!m_dataTag.isEmpty()) - output.append(QString(" (%1)").arg(m_dataTag)); - if (!desc.isEmpty()) { - int breakPos = desc.indexOf('('); - output.append(": ").append(desc.left(breakPos)); - if (selected) - output.append('\n').append(desc.mid(breakPos)); - } - break; - default: - output = desc; - if (!selected) - output = output.split('\n').first(); - } - return output; -} +QtTestResult::QtTestResult(const QString &id, const QString &name, + const Utils::FilePath &projectFile, TestType type, + const QString &functionName, const QString &dataTag) + : TestResult(id, name, {outputStringHook(functionName, dataTag)}) + , m_projectFile(projectFile) + , m_type(type) + , m_function(functionName) + , m_dataTag(dataTag) {} bool QtTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermediate) const { @@ -97,8 +102,8 @@ TestResult *QtTestResult::createIntermediateResultFor(const TestResult *other) { QTC_ASSERT(other, return nullptr); const QtTestResult *qtOther = static_cast(other); - QtTestResult *intermediate = new QtTestResult(qtOther->id(), qtOther->m_projectFile, - m_type, qtOther->name()); + QtTestResult *intermediate = new QtTestResult(qtOther->id(), qtOther->name(), qtOther->m_projectFile, + m_type); intermediate->m_function = qtOther->m_function; intermediate->m_dataTag = qtOther->m_dataTag; // intermediates will be needed only for data tags diff --git a/src/plugins/autotest/qtest/qttestresult.h b/src/plugins/autotest/qtest/qttestresult.h index b1efb138847..46d75d446fe 100644 --- a/src/plugins/autotest/qtest/qttestresult.h +++ b/src/plugins/autotest/qtest/qttestresult.h @@ -15,12 +15,8 @@ namespace Internal { class QtTestResult : public TestResult { public: - QtTestResult(const QString &id, const Utils::FilePath &projectFile, TestType type, - const QString &className); - const QString outputString(bool selected) const override; - - void setFunctionName(const QString &functionName) { m_function = functionName; } - void setDataTag(const QString &dataTag) { m_dataTag = dataTag; } + QtTestResult(const QString &id, const QString &name, const Utils::FilePath &projectFile, + TestType type, const QString &functionName = {}, const QString &dataTag = {}); bool isDirectParentOf(const TestResult *other, bool *needsIntermediate) const override; bool isIntermediateFor(const TestResult *other) const override; @@ -35,10 +31,10 @@ private: bool matchesTestCase(const TestTreeItem *item) const; bool matchesTestFunction(const TestTreeItem *item) const; - QString m_function; - QString m_dataTag; Utils::FilePath m_projectFile; TestType m_type; + QString m_function; + QString m_dataTag; }; } // namespace Internal diff --git a/src/plugins/autotest/testresult.cpp b/src/plugins/autotest/testresult.cpp index 8f233d40ef5..838df046695 100644 --- a/src/plugins/autotest/testresult.cpp +++ b/src/plugins/autotest/testresult.cpp @@ -8,14 +8,18 @@ namespace Autotest { -TestResult::TestResult(const QString &id, const QString &name) +TestResult::TestResult(const QString &id, const QString &name, const ResultHooks &hooks) : m_id(id) , m_name(name) + , m_hooks(hooks) { } const QString TestResult::outputString(bool selected) const { + if (m_hooks.outputString) + return m_hooks.outputString(*this, selected); + if (m_result == ResultType::Application) return m_id; return selected ? m_description : m_description.split('\n').first(); diff --git a/src/plugins/autotest/testresult.h b/src/plugins/autotest/testresult.h index 866388c2bb1..5130eb20ae8 100644 --- a/src/plugins/autotest/testresult.h +++ b/src/plugins/autotest/testresult.h @@ -58,14 +58,22 @@ inline auto qHash(const ResultType &result) return QT_PREPEND_NAMESPACE(qHash(int(result))); } +class TestResult; + +struct ResultHooks +{ + using OutputStringHook = std::function; + OutputStringHook outputString; +}; + class TestResult { public: TestResult() = default; - TestResult(const QString &id, const QString &name); + TestResult(const QString &id, const QString &name, const ResultHooks &hooks = {}); virtual ~TestResult() {} - virtual const QString outputString(bool selected) const; + const QString outputString(bool selected) const; virtual const ITestTreeItem *findTestTreeItem() const; QString id() const { return m_id; } @@ -95,6 +103,7 @@ private: QString m_description; Utils::FilePath m_file; int m_line = 0; + ResultHooks m_hooks; }; using TestResultPtr = QSharedPointer;