QTest: make failOnWarning() functional on temp objects destruction

We need to be able to handle warnings that may occur when temporary
objects, that were created in a test function, are destroyed.
For example, now we miss all warnings that might be triggered from
the object destructor, if the object's deletion was delayed (e.g. via
deleteLater()). Also we miss all the warnings that were triggered on
the test's cleanup() call.

To fix this we need simply move QTestLog::clearFailOnWarnings()
from QTestResult::finishedCurrentTestData() to the later stage,
i.e. into QTestLog::clearCurrentTestState() which is actually called
in appropriate time from QTestResult::finishedCurrentTestDataCleanup().

Same for QTestLog::clearIgnoreMessages(), since they are interrelated,
so we need to clear them at the same time.

We need this change for QML tests in particularly, to be able
fail on warnings that might be triggered from Component.onDestruction()
of some temporary test object.

Pick-to: 6.5
Change-Id: I58a57691f20761619f56bd1bea3a862f2c26f569
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 18aa36cf878a52b8fe991392098e9445c3d3bfe3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Vladimir Belyavsky 2023-11-17 02:16:58 +03:00 committed by Qt Cherry-pick Bot
parent 90ff2bc5c6
commit 10d88ca9db
9 changed files with 68 additions and 14 deletions

View File

@ -318,7 +318,6 @@ void QTestLog::clearIgnoreMessages()
QTest::IgnoreResultList::clearList(QTest::ignoreResultList); QTest::IgnoreResultList::clearList(QTest::ignoreResultList);
} }
void QTestLog::clearFailOnWarnings() void QTestLog::clearFailOnWarnings()
{ {
QTest::failOnWarningList.clear(); QTest::failOnWarningList.clear();
@ -326,6 +325,8 @@ void QTestLog::clearFailOnWarnings()
void QTestLog::clearCurrentTestState() void QTestLog::clearCurrentTestState()
{ {
clearIgnoreMessages();
clearFailOnWarnings();
QTest::currentTestState = QTest::Unresolved; QTest::currentTestState = QTest::Unresolved;
} }

View File

@ -149,13 +149,6 @@ void QTestResult::finishedCurrentTestData()
addFailure("QEXPECT_FAIL was called without any subsequent verification statements"); addFailure("QEXPECT_FAIL was called without any subsequent verification statements");
clearExpectFail(); clearExpectFail();
if (!QTest::hasFailed() && QTestLog::unhandledIgnoreMessages()) {
QTestLog::printUnhandledIgnoreMessages();
addFailure("Not all expected messages were received");
}
QTestLog::clearIgnoreMessages();
QTestLog::clearFailOnWarnings();
} }
/*! /*!
@ -175,6 +168,11 @@ void QTestResult::finishedCurrentTestData()
*/ */
void QTestResult::finishedCurrentTestDataCleanup() void QTestResult::finishedCurrentTestDataCleanup()
{ {
if (!QTest::hasFailed() && QTestLog::unhandledIgnoreMessages()) {
QTestLog::printUnhandledIgnoreMessages();
addFailure("Not all expected messages were received");
}
// If the current test hasn't failed or been skipped, then it passes. // If the current test hasn't failed or been skipped, then it passes.
if (!QTest::hasFailed() && !QTest::skipCurrentTest) { if (!QTest::hasFailed() && !QTest::skipCurrentTest) {
if (QTest::blacklistCurrentTest) if (QTest::blacklistCurrentTest)

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<testsuite name="tst_Warnings" timestamp="@TEST_START_TIME@" hostname="@HOSTNAME@" tests="15" failures="10" errors="0" skipped="0" time="@TEST_DURATION@"> <testsuite name="tst_Warnings" timestamp="@TEST_START_TIME@" hostname="@HOSTNAME@" tests="16" failures="11" errors="0" skipped="0" time="@TEST_DURATION@">
<properties> <properties>
<property name="QTestVersion" value="@INSERT_QT_VERSION_HERE@"/> <property name="QTestVersion" value="@INSERT_QT_VERSION_HERE@"/>
<property name="QtVersion" value="@INSERT_QT_VERSION_HERE@"/> <property name="QtVersion" value="@INSERT_QT_VERSION_HERE@"/>
@ -107,5 +107,10 @@
<skipped message="My cabbage! :("/> <skipped message="My cabbage! :("/>
</testcase> </testcase>
<testcase name="testFailOnWarningsAndIgnoreWarnings" classname="tst_Warnings" time="@TEST_DURATION@"/> <testcase name="testFailOnWarningsAndIgnoreWarnings" classname="tst_Warnings" time="@TEST_DURATION@"/>
<testcase name="testFailOnTemporaryObjectDestruction" classname="tst_Warnings" time="@TEST_DURATION@">
<failure type="fail" message="Received a warning that resulted in a failure:">
<![CDATA[Running low on toothpaste!]]>
</failure>
</testcase>
<testcase name="cleanupTestCase" classname="tst_Warnings" time="@TEST_DURATION@"/> <testcase name="cleanupTestCase" classname="tst_Warnings" time="@TEST_DURATION@"/>
</testsuite> </testsuite>

View File

@ -201,6 +201,13 @@ Ran out of cabbage!]]></Description>
<Incident type="pass" file="" line="0" /> <Incident type="pass" file="" line="0" />
<Duration msecs="0"/> <Duration msecs="0"/>
</TestFunction> </TestFunction>
<TestFunction name="testFailOnTemporaryObjectDestruction">
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/warnings/tst_warnings.cpp" line="0">
<Description><![CDATA[Received a warning that resulted in a failure:
Running low on toothpaste!]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="cleanupTestCase"> <TestFunction name="cleanupTestCase">
<Incident type="pass" file="" line="0" /> <Incident type="pass" file="" line="0" />
<Duration msecs="0"/> <Duration msecs="0"/>

View File

@ -159,8 +159,16 @@ Ran out of cabbage!
... ...
ok 13 - testFailOnWarningsThenSkip() # SKIP My cabbage! :( ok 13 - testFailOnWarningsThenSkip() # SKIP My cabbage! :(
ok 14 - testFailOnWarningsAndIgnoreWarnings() ok 14 - testFailOnWarningsAndIgnoreWarnings()
ok 15 - cleanupTestCase() not ok 15 - testFailOnTemporaryObjectDestruction()
1..15 ---
# tests 15 # Received a warning that resulted in a failure:
Running low on toothpaste!
at: tst_Warnings::testFailOnTemporaryObjectDestruction() (qtbase/tests/auto/testlib/selftests/warnings/tst_warnings.cpp:0)
file: qtbase/tests/auto/testlib/selftests/warnings/tst_warnings.cpp
line: 0
...
ok 16 - cleanupTestCase()
1..16
# tests 16
# pass 5 # pass 5
# fail 10 # fail 11

View File

@ -57,6 +57,9 @@
##teamcity[testFinished name='testFailOnWarningsThenSkip()' flowId='tst_Warnings'] ##teamcity[testFinished name='testFailOnWarningsThenSkip()' flowId='tst_Warnings']
##teamcity[testStarted name='testFailOnWarningsAndIgnoreWarnings()' flowId='tst_Warnings'] ##teamcity[testStarted name='testFailOnWarningsAndIgnoreWarnings()' flowId='tst_Warnings']
##teamcity[testFinished name='testFailOnWarningsAndIgnoreWarnings()' flowId='tst_Warnings'] ##teamcity[testFinished name='testFailOnWarningsAndIgnoreWarnings()' flowId='tst_Warnings']
##teamcity[testStarted name='testFailOnTemporaryObjectDestruction()' flowId='tst_Warnings']
##teamcity[testFailed name='testFailOnTemporaryObjectDestruction()' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/warnings/tst_warnings.cpp(0)|]' details='Received a warning that resulted in a failure:|nRunning low on toothpaste!' flowId='tst_Warnings']
##teamcity[testFinished name='testFailOnTemporaryObjectDestruction()' flowId='tst_Warnings']
##teamcity[testStarted name='cleanupTestCase()' flowId='tst_Warnings'] ##teamcity[testStarted name='cleanupTestCase()' flowId='tst_Warnings']
##teamcity[testFinished name='cleanupTestCase()' flowId='tst_Warnings'] ##teamcity[testFinished name='cleanupTestCase()' flowId='tst_Warnings']
##teamcity[testSuiteFinished name='tst_Warnings' flowId='tst_Warnings'] ##teamcity[testSuiteFinished name='tst_Warnings' flowId='tst_Warnings']

View File

@ -69,6 +69,9 @@ Ran out of cabbage!
SKIP : tst_Warnings::testFailOnWarningsThenSkip() My cabbage! :( SKIP : tst_Warnings::testFailOnWarningsThenSkip() My cabbage! :(
Loc: [qtbase/tests/auto/testlib/selftests/warnings/tst_warnings.cpp(0)] Loc: [qtbase/tests/auto/testlib/selftests/warnings/tst_warnings.cpp(0)]
PASS : tst_Warnings::testFailOnWarningsAndIgnoreWarnings() PASS : tst_Warnings::testFailOnWarningsAndIgnoreWarnings()
FAIL! : tst_Warnings::testFailOnTemporaryObjectDestruction() Received a warning that resulted in a failure:
Running low on toothpaste!
Loc: [qtbase/tests/auto/testlib/selftests/warnings/tst_warnings.cpp(0)]
PASS : tst_Warnings::cleanupTestCase() PASS : tst_Warnings::cleanupTestCase()
Totals: 5 passed, 10 failed, 0 skipped, 0 blacklisted, 0ms Totals: 5 passed, 11 failed, 0 skipped, 0 blacklisted, 0ms
********* Finished testing of tst_Warnings ********* ********* Finished testing of tst_Warnings *********

View File

@ -203,6 +203,13 @@ Ran out of cabbage!]]></Description>
<Incident type="pass" file="" line="0" /> <Incident type="pass" file="" line="0" />
<Duration msecs="0"/> <Duration msecs="0"/>
</TestFunction> </TestFunction>
<TestFunction name="testFailOnTemporaryObjectDestruction">
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/warnings/tst_warnings.cpp" line="0">
<Description><![CDATA[Received a warning that resulted in a failure:
Running low on toothpaste!]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="cleanupTestCase"> <TestFunction name="cleanupTestCase">
<Incident type="pass" file="" line="0" /> <Incident type="pass" file="" line="0" />
<Duration msecs="0"/> <Duration msecs="0"/>

View File

@ -27,6 +27,7 @@ private slots:
void testFailOnWarningsThenSkip(); void testFailOnWarningsThenSkip();
#endif #endif
void testFailOnWarningsAndIgnoreWarnings(); void testFailOnWarningsAndIgnoreWarnings();
void testFailOnTemporaryObjectDestruction();
}; };
void tst_Warnings::testWarnings() void tst_Warnings::testWarnings()
@ -208,6 +209,27 @@ void tst_Warnings::testFailOnWarningsAndIgnoreWarnings()
qWarning(warningStr); qWarning(warningStr);
} }
void tst_Warnings::testFailOnTemporaryObjectDestruction()
{
QTest::failOnWarning("Running low on toothpaste!");
QTest::ignoreMessage(QtWarningMsg, "Ran out of cabbage!");
class TestObject : public QObject
{
public:
~TestObject()
{
// Shouldn't fail - ignored
qWarning("Ran out of cabbage!");
// Should fail
qWarning("Running low on toothpaste!");
}
};
QScopedPointer<TestObject, QScopedPointerDeleteLater> testObject(new TestObject);
QVERIFY(testObject);
}
QTEST_MAIN(tst_Warnings) QTEST_MAIN(tst_Warnings)
#include "tst_warnings.moc" #include "tst_warnings.moc"