summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/testlib/qtestcase.cpp48
-rw-r--r--src/testlib/qtestlog.cpp68
-rw-r--r--src/testlib/qtestlog_p.h3
-rw-r--r--src/testlib/qtestresult.cpp3
4 files changed, 95 insertions, 27 deletions
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 9a93c41b5c..673605307f 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -946,33 +946,38 @@ void TestMethods::invokeTestOnData(int index) const
do {
if (m_initMethod.isValid())
m_initMethod.invoke(QTest::currentTestObject, Qt::DirectConnection);
- if (QTestResult::skipCurrentTest() || QTestResult::currentTestFailed())
- break;
- QBenchmarkTestMethodData::current->result = QBenchmarkResult();
- QBenchmarkTestMethodData::current->resultAccepted = false;
+ const bool initQuit =
+ QTestResult::skipCurrentTest() || QTestResult::currentTestFailed();
+ if (!initQuit) {
+ QBenchmarkTestMethodData::current->result = QBenchmarkResult();
+ QBenchmarkTestMethodData::current->resultAccepted = false;
- QBenchmarkGlobalData::current->context.tag =
- QLatin1String(
- QTestResult::currentDataTag()
- ? QTestResult::currentDataTag() : "");
+ QBenchmarkGlobalData::current->context.tag = QLatin1String(
+ QTestResult::currentDataTag() ? QTestResult::currentDataTag() : "");
- invokeOk = m_methods[index].invoke(QTest::currentTestObject, Qt::DirectConnection);
- if (!invokeOk)
- QTestResult::addFailure("Unable to execute slot", __FILE__, __LINE__);
+ invokeOk = m_methods[index].invoke(QTest::currentTestObject, Qt::DirectConnection);
+ if (!invokeOk)
+ QTestResult::addFailure("Unable to execute slot", __FILE__, __LINE__);
- isBenchmark = QBenchmarkTestMethodData::current->isBenchmark();
+ isBenchmark = QBenchmarkTestMethodData::current->isBenchmark();
+ } else {
+ invokeOk = false;
+ }
QTestResult::finishedCurrentTestData();
- if (m_cleanupMethod.isValid())
- m_cleanupMethod.invoke(QTest::currentTestObject, Qt::DirectConnection);
+ if (!initQuit) {
+ if (m_cleanupMethod.isValid())
+ m_cleanupMethod.invoke(QTest::currentTestObject, Qt::DirectConnection);
- // Process any deleteLater(), like event-loop based apps would do. Fixes memleak reports.
- if (QCoreApplication::instance())
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
-
- // If the test isn't a benchmark, finalize the result after cleanup() has finished.
+ // Process any deleteLater(), used by event-loop-based apps.
+ // Fixes memleak reports.
+ if (QCoreApplication::instance())
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ }
+ // If the test isn't a benchmark, finalize the result after
+ // cleanup() has finished (or init has lead us to skip the test).
if (!isBenchmark)
QTestResult::finishedCurrentTestDataCleanup();
@@ -1522,7 +1527,7 @@ void TestMethods::invokeTests(QObject *testObject) const
QSignalDumper::startDump();
- if (!QTestResult::skipCurrentTest() && !QTest::currentTestFailed()) {
+ if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) {
if (m_initTestCaseMethod.isValid())
m_initTestCaseMethod.invoke(testObject, Qt::DirectConnection);
@@ -1544,12 +1549,15 @@ void TestMethods::invokeTests(QObject *testObject) const
}
}
+ const bool wasSkipped = QTestResult::skipCurrentTest();
QTestResult::setSkipCurrentTest(false);
QTestResult::setBlacklistCurrentTest(false);
QTestResult::setCurrentTestFunction("cleanupTestCase");
if (m_cleanupTestCaseMethod.isValid())
m_cleanupTestCaseMethod.invoke(testObject, Qt::DirectConnection);
QTestResult::finishedCurrentTestData();
+ // Restore skip state as it affects decision on whether we passed:
+ QTestResult::setSkipCurrentTest(wasSkipped || QTestResult::skipCurrentTest());
QTestResult::finishedCurrentTestDataCleanup();
}
QTestResult::finishedCurrentTestFunction();
diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp
index c90850e786..4f0e3a43bc 100644
--- a/src/testlib/qtestlog.cpp
+++ b/src/testlib/qtestlog.cpp
@@ -111,6 +111,7 @@ namespace QTest {
int passes = 0;
int skips = 0;
int blacklists = 0;
+ enum { Unresolved, Passed, Skipped, Suppressed, Failed } currentTestState;
struct IgnoreResultList
{
@@ -345,19 +346,27 @@ void QTestLog::clearIgnoreMessages()
QTest::IgnoreResultList::clearList(QTest::ignoreResultList);
}
+
void QTestLog::clearFailOnWarnings()
{
QTest::failOnWarningList.clear();
}
+void QTestLog::clearCurrentTestState()
+{
+ QTest::currentTestState = QTest::Unresolved;
+}
+
void QTestLog::addPass(const char *msg)
{
if (printAvailableTags)
return;
QTEST_ASSERT(msg);
+ Q_ASSERT(QTest::currentTestState == QTest::Unresolved);
++QTest::passes;
+ QTest::currentTestState = QTest::Passed;
FOREACH_TEST_LOGGER
logger->addIncident(QAbstractTestLogger::Pass, msg);
@@ -367,8 +376,18 @@ void QTestLog::addFail(const char *msg, const char *file, int line)
{
QTEST_ASSERT(msg);
- ++QTest::fails;
+ if (QTest::currentTestState == QTest::Unresolved) {
+ ++QTest::fails;
+ } else {
+ // After an XPASS/Continue, or fail or skip in a function the test
+ // calls, we can subsequently fail.
+ Q_ASSERT(QTest::currentTestState == QTest::Failed
+ || QTest::currentTestState == QTest::Skipped);
+ }
+ // It is up to particular loggers to decide whether to report such
+ // subsequent failures; they may carry useful information.
+ QTest::currentTestState = QTest::Failed;
FOREACH_TEST_LOGGER
logger->addIncident(QAbstractTestLogger::Fail, msg, file, line);
}
@@ -387,8 +406,16 @@ void QTestLog::addXPass(const char *msg, const char *file, int line)
{
QTEST_ASSERT(msg);
- ++QTest::fails;
+ if (QTest::currentTestState == QTest::Unresolved) {
+ ++QTest::fails;
+ } else {
+ // After an XPASS/Continue, we can subsequently XPASS again.
+ // Likewise after a fail or skip in a function called by the test.
+ Q_ASSERT(QTest::currentTestState == QTest::Failed
+ || QTest::currentTestState == QTest::Skipped);
+ }
+ QTest::currentTestState = QTest::Failed;
FOREACH_TEST_LOGGER
logger->addIncident(QAbstractTestLogger::XPass, msg, file, line);
}
@@ -396,8 +423,10 @@ void QTestLog::addXPass(const char *msg, const char *file, int line)
void QTestLog::addBPass(const char *msg)
{
QTEST_ASSERT(msg);
+ Q_ASSERT(QTest::currentTestState == QTest::Unresolved);
- ++QTest::blacklists;
+ ++QTest::blacklists; // Not passes ?
+ QTest::currentTestState = QTest::Suppressed;
FOREACH_TEST_LOGGER
logger->addIncident(QAbstractTestLogger::BlacklistedPass, msg);
@@ -407,8 +436,16 @@ void QTestLog::addBFail(const char *msg, const char *file, int line)
{
QTEST_ASSERT(msg);
- ++QTest::blacklists;
+ if (QTest::currentTestState == QTest::Unresolved) {
+ ++QTest::blacklists;
+ } else {
+ // After a BXPASS/Continue, we can subsequently fail.
+ // Likewise after a fail or skip in a function called by a test.
+ Q_ASSERT(QTest::currentTestState == QTest::Suppressed
+ || QTest::currentTestState == QTest::Skipped);
+ }
+ QTest::currentTestState = QTest::Suppressed;
FOREACH_TEST_LOGGER
logger->addIncident(QAbstractTestLogger::BlacklistedFail, msg, file, line);
}
@@ -417,8 +454,16 @@ void QTestLog::addBXPass(const char *msg, const char *file, int line)
{
QTEST_ASSERT(msg);
- ++QTest::blacklists;
+ if (QTest::currentTestState == QTest::Unresolved) {
+ ++QTest::blacklists;
+ } else {
+ // After a BXPASS/Continue, we may BXPASS again.
+ // Likewise after a fail or skip in a function called by a test.
+ Q_ASSERT(QTest::currentTestState == QTest::Suppressed
+ || QTest::currentTestState == QTest::Skipped);
+ }
+ QTest::currentTestState = QTest::Suppressed;
FOREACH_TEST_LOGGER
logger->addIncident(QAbstractTestLogger::BlacklistedXPass, msg, file, line);
}
@@ -437,7 +482,18 @@ void QTestLog::addSkip(const char *msg, const char *file, int line)
{
QTEST_ASSERT(msg);
- ++QTest::skips;
+ if (QTest::currentTestState == QTest::Unresolved) {
+ ++QTest::skips;
+ QTest::currentTestState = QTest::Skipped;
+ } else {
+ // After an B?XPASS/Continue, we might subsequently skip.
+ // Likewise after a skip in a function called by a test.
+ Q_ASSERT(QTest::currentTestState == QTest::Suppressed
+ || QTest::currentTestState == QTest::Failed
+ || QTest::currentTestState == QTest::Skipped);
+ }
+ // It is up to particular loggers to decide whether to report such
+ // subsequent skips; they may carry useful information.
FOREACH_TEST_LOGGER
logger->addIncident(QAbstractTestLogger::Skip, msg, file, line);
diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h
index cc24360bed..36e38a33cb 100644
--- a/src/testlib/qtestlog_p.h
+++ b/src/testlib/qtestlog_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtTest module of the Qt Toolkit.
@@ -113,6 +113,7 @@ public:
static void printUnhandledIgnoreMessages();
static void clearIgnoreMessages();
static void clearFailOnWarnings();
+ static void clearCurrentTestState();
static void warn(const char *msg, const char *file, int line);
static void info(const char *msg, const char *file, int line);
diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp
index ae40164392..a3a0bd08b3 100644
--- a/src/testlib/qtestresult.cpp
+++ b/src/testlib/qtestresult.cpp
@@ -219,6 +219,7 @@ void QTestResult::finishedCurrentTestDataCleanup()
QTestLog::addPass("");
}
+ QTestLog::clearCurrentTestState();
QTest::resetFailed();
}
@@ -232,6 +233,7 @@ void QTestResult::finishedCurrentTestDataCleanup()
*/
void QTestResult::finishedCurrentTestFunction()
{
+ QTestLog::clearCurrentTestState(); // Needed if _data() skipped.
QTestLog::leaveTestFunction();
QTest::currentTestFunc = nullptr;
@@ -296,6 +298,7 @@ static bool checkStatement(bool statement, const char *msg, const char *file, in
QTestLog::addXPass(msg, file, line);
QTest::setFailed(true);
+ // Should B?XPass always (a) continue or (b) abort, regardless of mode ?
bool doContinue = (QTest::expectFailMode == QTest::Continue);
clearExpectFail();
return doContinue;