diff --git a/src/corelib/io/qfilesystemwatcher_polling.cpp b/src/corelib/io/qfilesystemwatcher_polling.cpp index a74205b713..d34c8c49e8 100644 --- a/src/corelib/io/qfilesystemwatcher_polling.cpp +++ b/src/corelib/io/qfilesystemwatcher_polling.cpp @@ -3,6 +3,7 @@ #include "qfilesystemwatcher_polling_p.h" +#include #include #include @@ -12,6 +13,8 @@ using namespace std::chrono_literals; QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + static constexpr auto PollingInterval = 1s; QPollingFileSystemWatcherEngine::QPollingFileSystemWatcherEngine(QObject *parent) @@ -45,10 +48,17 @@ QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths, sg.dismiss(); } + std::chrono::milliseconds interval = PollingInterval; +#ifdef QT_BUILD_INTERNAL + if (Q_UNLIKELY(parent()->objectName().startsWith("_qt_autotest_force_engine_"_L1))) { + interval = 10ms; // Special case to speed up the unittests + } +#endif + if ((!this->files.isEmpty() || !this->directories.isEmpty()) && !timer.isActive()) { - timer.start(PollingInterval, this); + timer.start(interval, this); } return unhandled; diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp index 9dabefab71..217182ab6a 100644 --- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp +++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp @@ -23,6 +23,19 @@ #include #endif +using namespace std::chrono_literals; + +#if defined(Q_OS_QNX) +// Longer polling times on QNX, otherwise the tests fail on the CI +constexpr auto nativeEngineTimeout = 1s; +constexpr auto pollingEngineTimeout = 1s; +constexpr bool isQNX = true; +#else +constexpr auto nativeEngineTimeout = 0ms; +constexpr auto pollingEngineTimeout = 20ms; +constexpr bool isQNX = false; +#endif + /* All tests need to run in temporary directories not used * by the application to avoid non-deterministic failures on Windows * due to locked directories and left-overs from previous tests. */ @@ -130,18 +143,19 @@ void tst_QFileSystemWatcher::basicTest() watcher.setObjectName(QLatin1String("_qt_autotest_force_engine_") + backend); QVERIFY(watcher.addPath(testFile.fileName())); + const bool isPollerBackend = backend == u"poller"; + QSignalSpy changedSpy(&watcher, &QFileSystemWatcher::fileChanged); QVERIFY(changedSpy.isValid()); QEventLoop eventLoop; QTimer timer; + timer.setInterval(isPollerBackend ? pollingEngineTimeout : nativeEngineTimeout); connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); // modify the file, should get a signal from the watcher - // resolution of the modification time is system dependent, but it's at most 1 second when using - // the polling engine. I've heard rumors that FAT32 has a 2 second resolution. So, we have to - // wait a bit before we can modify the file (hrmph)... - QTest::qWait(2000); + if (isPollerBackend || isQNX) + QTest::qWait(pollingEngineTimeout); testFile.open(QIODevice::WriteOnly | QIODevice::Append); testFile.write(QByteArray("world")); @@ -162,8 +176,8 @@ void tst_QFileSystemWatcher::basicTest() testFile.write(QByteArray("hello universe!")); testFile.close(); - // waiting max 5 seconds for notification for file modification to trigger - timer.start(5000); + // waiting for notification for file modification to trigger + timer.start(); eventLoop.exec(); QCOMPARE(changedSpy.size(), 0); @@ -206,8 +220,8 @@ void tst_QFileSystemWatcher::basicTest() QVERIFY(watcher.removePath(testFile.fileName())); testFile.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOther); - // waiting max 5 seconds for notification for file modification to trigger - timer.start(5000); + // waiting for notification for file modification to trigger + timer.start(); eventLoop.exec(); QCOMPARE(changedSpy.size(), 0); @@ -234,8 +248,8 @@ void tst_QFileSystemWatcher::basicTest() testFile.write(QByteArray("hello")); testFile.close(); - // waiting max 5 seconds for notification for file recreation to trigger - timer.start(5000); + // waiting for notification for file recreation to trigger + timer.start(); eventLoop.exec(); QCOMPARE(changedSpy.size(), 0); @@ -282,16 +296,18 @@ void tst_QFileSystemWatcher::watchDirectory() watcher.setObjectName(QLatin1String("_qt_autotest_force_engine_") + backend); QVERIFY(watcher.addPaths(testDirs).isEmpty()); + const bool isPollerBackend = backend == u"poller"; + QSignalSpy changedSpy(&watcher, &QFileSystemWatcher::directoryChanged); QVERIFY(changedSpy.isValid()); QEventLoop eventLoop; QTimer timer; + timer.setInterval(isPollerBackend ? pollingEngineTimeout : nativeEngineTimeout); connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); - // resolution of the modification time is system dependent, but it's at most 1 second when using - // the polling engine. From what I know, FAT32 has a 2 second resolution. So we have to - // wait before modifying the directory... - QTest::qWait(2000); + if (isPollerBackend || isQNX) + QTest::qWait(pollingEngineTimeout); + // remove the watch, should not get notification of a new file QVERIFY(watcher.removePaths(testDirs).isEmpty()); for (const auto &testFileName : testFiles) { @@ -300,8 +316,8 @@ void tst_QFileSystemWatcher::watchDirectory() testFile.close(); } - // waiting max 5 seconds for notification for file recreationg to trigger - timer.start(5000); + // waiting for notification for file recreation to trigger + timer.start(); eventLoop.exec(); QCOMPARE(changedSpy.size(), 0); @@ -312,7 +328,7 @@ void tst_QFileSystemWatcher::watchDirectory() for (const auto &testFileName : testFiles) QVERIFY(QFile::remove(testFileName)); - timer.start(5000); + timer.start(); eventLoop.exec(); // remove the directory, should get a signal from the watcher @@ -339,7 +355,7 @@ void tst_QFileSystemWatcher::watchDirectory() QCOMPARE(count, 2); // flush pending signals (like the one from the rmdir above) - timer.start(5000); + timer.start(); eventLoop.exec(); changedSpy.clear(); @@ -351,8 +367,8 @@ void tst_QFileSystemWatcher::watchDirectory() } } - // waiting max 5 seconds for notification for dir recreation to trigger - timer.start(5000); + // waiting for notification for dir recreation to trigger + timer.start(); eventLoop.exec(); QCOMPARE(changedSpy.size(), 0); @@ -550,17 +566,18 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory() QVERIFY(watcher.addPath(testDir.absolutePath())); QVERIFY(watcher.addPath(testFileName)); + const bool isPollerBackend = backend == u"poller"; + QSignalSpy fileChangedSpy(&watcher, &QFileSystemWatcher::fileChanged); FileSystemWatcherSpy dirChangedSpy(&watcher, FileSystemWatcherSpy::SpyOnDirectoryChanged); QVERIFY(fileChangedSpy.isValid()); QEventLoop eventLoop; QTimer timer; + timer.setInterval(isPollerBackend ? pollingEngineTimeout : nativeEngineTimeout); connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); - // resolution of the modification time is system dependent, but it's at most 1 second when using - // the polling engine. From what I know, FAT32 has a 2 second resolution. So we have to - // wait before modifying the directory... - QTest::qWait(2000); + if (isPollerBackend || isQNX) + QTest::qWait(pollingEngineTimeout); QVERIFY2(testFile.open(QIODevice::WriteOnly | QIODevice::Truncate), msgFileOperationFailed("open", testFile)); QVERIFY2(testFile.write(QByteArrayLiteral("hello again")), msgFileOperationFailed("write", testFile)); @@ -580,7 +597,7 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory() QVERIFY2(secondFile.write(QByteArrayLiteral("Foo")) > 0, msgFileOperationFailed("write", secondFile)); secondFile.close(); - timer.start(3000); + timer.start(); eventLoop.exec(); int fileChangedSpyCount = fileChangedSpy.size(); #ifdef Q_OS_WIN @@ -604,7 +621,7 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory() QVERIFY(!watcher.removePath(testFileName)); QVERIFY(QFile::remove(secondFileName)); - timer.start(3000); + timer.start(); eventLoop.exec(); QCOMPARE(fileChangedSpy.size(), 0); QCOMPARE(dirChangedSpy.count(), 1);