From cc331ef757aabe817e72f30d036acd6d43af1343 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Mon, 2 Sep 2024 10:43:15 +0800 Subject: [PATCH] TestLib: enable watchdog during _data and init/cleanupTestCase The watchdog is not enabled when running initTestCase and friends. We therefore miss some deadlocks in these methods. Task-number: QTBUG-128510 Change-Id: I119a1ee04c45df00b62f9d5990075e4bf8814142 Reviewed-by: Edward Welbourne (cherry picked from commit 9154bb8f19815acc64b69b85a8c0e5ab8b96ec49) Reviewed-by: Qt Cherry-pick Bot --- src/testlib/qtestcase.cpp | 46 +++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index e3deb12a3b2..78e8038c05b 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -1265,6 +1265,17 @@ public: #endif // QT_CONFIG(thread) +template +void runWithWatchdog(std::optional &watchDog, Functor &&f) +{ + if (watchDog) + watchDog->beginTest(); + + f(); + + if (watchDog) + watchDog->testFinished(); +} static void printUnknownDataTagError(QLatin1StringView name, QLatin1StringView tag, const QTestTable &lTable, const QTestTable &gTable) @@ -1336,7 +1347,9 @@ bool TestMethods::invokeTest(int index, QLatin1StringView tag, std::optional= dataCount ? nullptr : table.testData(curDataIndex)); QTestPrivate::qtestMouseButtons = Qt::NoButton; - if (watchDog) - watchDog->beginTest(); - QTest::lastMouseTimestamp += 500; // Maintain at least 500ms mouse event timestamps between each test function call - invokeTestOnData(index); - if (watchDog) - watchDog->testFinished(); + + // Maintain at least 500ms mouse event timestamps between each test function + // call + QTest::lastMouseTimestamp += 500; + + runWithWatchdog(watchDog, [this, index] { + invokeTestOnData(index); + }); } if (!tag.isEmpty() && !globalDataCount) @@ -1681,8 +1696,6 @@ void TestMethods::invokeTests(QObject *testObject) const { const QMetaObject *metaObject = testObject->metaObject(); QTEST_ASSERT(metaObject); - QTestResult::setCurrentTestFunction("initTestCase"); - invokeTestMethodIfValid(m_initTestCaseDataMethod, testObject); std::optional watchDog = std::nullopt; if (!CrashHandler::alreadyDebugging() @@ -1693,10 +1706,18 @@ void TestMethods::invokeTests(QObject *testObject) const watchDog.emplace(); } + QTestResult::setCurrentTestFunction("initTestCase"); + runWithWatchdog(watchDog, [this, testObject] { + invokeTestMethodIfValid(m_initTestCaseDataMethod, testObject); + }); + QSignalDumper::startDump(); if (!QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed()) { - invokeTestMethodIfValid(m_initTestCaseMethod, testObject); + + runWithWatchdog(watchDog, [this, testObject] { + invokeTestMethodIfValid(m_initTestCaseMethod, testObject); + }); // finishedCurrentTestDataCleanup() resets QTestResult::currentTestFailed(), so use a local copy. const bool previousFailed = QTestResult::currentTestFailed(); @@ -1720,7 +1741,10 @@ void TestMethods::invokeTests(QObject *testObject) const QTestResult::setSkipCurrentTest(false); QTestResult::setBlacklistCurrentTest(false); QTestResult::setCurrentTestFunction("cleanupTestCase"); - invokeTestMethodIfValid(m_cleanupTestCaseMethod, testObject); + runWithWatchdog(watchDog, [this, testObject] { + invokeTestMethodIfValid(m_cleanupTestCaseMethod, testObject); + }); + QTestResult::finishedCurrentTestData(); // Restore skip state as it affects decision on whether we passed: QTestResult::setSkipCurrentTest(wasSkipped || QTestResult::skipCurrentTest());