diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2020-12-03 00:15:53 +0100 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2020-12-04 14:09:46 +0000 |
commit | a1a55d5b9301c4e7ea6f9ff1d1c5096081019a4d (patch) | |
tree | 7ab0c1f89cdca4484e5ea5635129d39b8de652d4 /src | |
parent | bc093cd294cbf48eb93b776fc0b927f0a43fa603 (diff) |
QTestLib: add a abort-on-fail environment variable
When debugging a spurious failure it's extremely useful to
run the test repeadtly into a debugger until a failure appears.
When that happens, one wants to immediately start debugging.
In so far, this has only been possible by placing breakpoints
inside Qt itself (when a failure is logged). Add another way:
an env variable, similar to QT_FATAL_WARNINGS, that makes
any failure fatal (terminate() gets called. Bonus: you can
control the termination handler!)
[ChangeLog][QtTestLib][QtTest] When the QTEST_FATAL_FAIL
environment variable is set to a non-zero value, a test
immediately aborts its execution. This is useful to debug
intermittent failures.
Change-Id: If2395f964ea482c30b8c8feab98db7fdee701cd3
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Jason McDonald <macadder1@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/testlib/doc/src/qttestlib-manual.qdoc | 6 | ||||
-rw-r--r-- | src/testlib/qtestresult.cpp | 52 |
2 files changed, 47 insertions, 11 deletions
diff --git a/src/testlib/doc/src/qttestlib-manual.qdoc b/src/testlib/doc/src/qttestlib-manual.qdoc index 73c010888f..9073cc7c88 100644 --- a/src/testlib/doc/src/qttestlib-manual.qdoc +++ b/src/testlib/doc/src/qttestlib-manual.qdoc @@ -374,6 +374,12 @@ \li \c QTEST_DISABLE_STACK_DUMP \br Setting this variable to a non-zero value will prevent Qt Test from printing a stacktrace in case an autotest times out or crashes. + \li \c QTEST_FATAL_FAIL \br + Setting this variable to a non-zero value will cause a failure in + an autotest to immediately abort the entire autotest. This is useful + to e.g. debug an unstable or intermittent failure in a test, by + launching the test in a debugger. Support for this variable has been + added in Qt 6.1. \endlist \section1 Creating a Benchmark diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp index a87d2f82c1..eeaea83357 100644 --- a/src/testlib/qtestresult.cpp +++ b/src/testlib/qtestresult.cpp @@ -57,11 +57,41 @@ QT_BEGIN_NAMESPACE namespace QTest { + namespace Internal { + static bool failed = false; + } + + static void setFailed(bool failed) + { + static const bool fatalFailure = []() { + static const char * const environmentVar = "QTEST_FATAL_FAIL"; + if (!qEnvironmentVariableIsSet(environmentVar)) + return false; + + bool ok; + const int fatal = qEnvironmentVariableIntValue(environmentVar, &ok); + return ok && fatal; + }(); + + if (failed && fatalFailure) + qTerminate(); + Internal::failed = failed; + } + + static void resetFailed() + { + setFailed(false); + } + + static bool hasFailed() + { + return Internal::failed; + } + static QTestData *currentTestData = nullptr; static QTestData *currentGlobalTestData = nullptr; static const char *currentTestFunc = nullptr; static const char *currentTestObjectName = nullptr; - static bool failed = false; static bool skipCurrentTest = false; static bool blacklistCurrentTest = false; @@ -75,7 +105,7 @@ void QTestResult::reset() QTest::currentGlobalTestData = nullptr; QTest::currentTestFunc = nullptr; QTest::currentTestObjectName = nullptr; - QTest::failed = false; + QTest::resetFailed(); QTest::expectFailComment = nullptr; QTest::expectFailMode = 0; @@ -91,7 +121,7 @@ void QTestResult::setBlacklistCurrentTest(bool b) bool QTestResult::currentTestFailed() { - return QTest::failed; + return QTest::hasFailed(); } QTestData *QTestResult::currentGlobalTestData() @@ -112,7 +142,7 @@ void QTestResult::setCurrentGlobalTestData(QTestData *data) void QTestResult::setCurrentTestData(QTestData *data) { QTest::currentTestData = data; - QTest::failed = false; + QTest::resetFailed(); if (data) QTestLog::enterTestData(data); } @@ -120,7 +150,7 @@ void QTestResult::setCurrentTestData(QTestData *data) void QTestResult::setCurrentTestFunction(const char *func) { QTest::currentTestFunc = func; - QTest::failed = false; + QTest::resetFailed(); if (func) QTestLog::enterTestFunction(func); } @@ -140,7 +170,7 @@ void QTestResult::finishedCurrentTestData() } clearExpectFail(); - if (!QTest::failed && QTestLog::unhandledIgnoreMessages()) { + if (!QTest::hasFailed() && QTestLog::unhandledIgnoreMessages()) { QTestLog::printUnhandledIgnoreMessages(); addFailure("Not all expected messages were received", "Unknown File", 0); } @@ -150,20 +180,20 @@ void QTestResult::finishedCurrentTestData() void QTestResult::finishedCurrentTestDataCleanup() { // If the current test hasn't failed or been skipped, then it passes. - if (!QTest::failed && !QTest::skipCurrentTest) { + if (!QTest::hasFailed() && !QTest::skipCurrentTest) { if (QTest::blacklistCurrentTest) QTestLog::addBPass(""); else QTestLog::addPass(""); } - QTest::failed = false; + QTest::resetFailed(); } void QTestResult::finishedCurrentTestFunction() { QTest::currentTestFunc = nullptr; - QTest::failed = false; + QTest::resetFailed(); QTestLog::leaveTestFunction(); } @@ -226,7 +256,7 @@ static bool checkStatement(bool statement, const char *msg, const char *file, in else QTestLog::addXPass(msg, file, line); - QTest::failed = true; + QTest::setFailed(true); bool doContinue = (QTest::expectFailMode == QTest::Continue); clearExpectFail(); return doContinue; @@ -425,7 +455,7 @@ void QTestResult::addFailure(const char *message, const char *file, int line) QTestLog::addBFail(message, file, line); else QTestLog::addFail(message, file, line); - QTest::failed = true; + QTest::setFailed(true); } void QTestResult::addSkip(const char *message, const char *file, int line) |