From 0be6cd3bf723d3b335e966fceaf5c9ea0254c706 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Tue, 7 Feb 2017 21:30:55 +0100 Subject: [PATCH] Fix FolderWatcherTest on macOS and Windows - We need to use a QGuiApplication on macOS or else we don't get notifications - Switch to use QSignalSpy rather than lists and sleeps - Use system() for all modifications since we pass kFSEventStreamCreateFlagIgnoreSelf - Keep using the local process on Windows since it catches its own events --- test/testfolderwatcher.cpp | 229 ++++++++++++++++++++----------------- 1 file changed, 122 insertions(+), 107 deletions(-) diff --git a/test/testfolderwatcher.cpp b/test/testfolderwatcher.cpp index 89d5d62d8..b5edc9371 100644 --- a/test/testfolderwatcher.cpp +++ b/test/testfolderwatcher.cpp @@ -10,163 +10,176 @@ #include "folderwatcher.h" #include "utility.h" +void touch(const QString &file) +{ +#ifdef Q_OS_WIN + OCC::Utility::writeRandomFile(file); +#else + QString cmd; + cmd = QString("touch %1").arg(file); + qDebug() << "Command: " << cmd; + system(cmd.toLocal8Bit()); +#endif +} + +void mkdir(const QString &file) +{ +#ifdef Q_OS_WIN + QDir dir; + dir.mkdir(file); +#else + QString cmd = QString("mkdir %1").arg(file); + qDebug() << "Command: " << cmd; + system(cmd.toLocal8Bit()); +#endif +} + +void rmdir(const QString &file) +{ +#ifdef Q_OS_WIN + QDir dir; + dir.rmdir(file); +#else + QString cmd = QString("rmdir %1").arg(file); + qDebug() << "Command: " << cmd; + system(cmd.toLocal8Bit()); +#endif +} + +void rm(const QString &file) +{ +#ifdef Q_OS_WIN + QFile::remove(file); +#else + QString cmd = QString("rm %1").arg(file); + qDebug() << "Command: " << cmd; + system(cmd.toLocal8Bit()); +#endif +} + +void mv(const QString &file1, const QString &file2) +{ +#ifdef Q_OS_WIN + QFile::rename(file1, file2); +#else + QString cmd = QString("mv %1 %2").arg(file1, file2); + qDebug() << "Command: " << cmd; + system(cmd.toLocal8Bit()); +#endif +} + using namespace OCC; class TestFolderWatcher : public QObject { Q_OBJECT -public slots: - void slotFolderChanged( const QString& path ) { - if (_skipNotifications.contains(path)) { - return; - } - if (_requiredNotifications.contains(path)) { - _receivedNotifications.insert(path); - } - } - - void slotEnd() { // in case something goes wrong... - _loop.quit(); - QVERIFY2(1 == 0, "Loop hang!"); - } - -private: - QString _root; - FolderWatcher *_watcher; - QEventLoop _loop; - QTimer _timer; - QSet _requiredNotifications; - QSet _receivedNotifications; - QSet _skipNotifications; + QTemporaryDir _root; + QString _rootPath; + QScopedPointer _watcher; + QScopedPointer _pathChangedSpy; - void processAndWait() + bool waitForPathChanged(const QString &path) { - _loop.processEvents(); - Utility::usleep(200000); - _loop.processEvents(); + QElapsedTimer t; + t.start(); + while (t.elapsed() < 5000) { + // Check if it was already reported as changed by the watcher + for (int i = 0; i < _pathChangedSpy->size(); ++i) { + const auto &args = _pathChangedSpy->at(i); + if (args.first().toString() == path) + return true; + } + // Wait a bit and test again (don't bother checking if we timed out or not) + _pathChangedSpy->wait(200); + } + return false; } -private slots: - void initTestCase() { +public: + TestFolderWatcher() { qsrand(QTime::currentTime().msec()); - _root = QDir::tempPath() + "/" + "test_" + QString::number(qrand()); - qDebug() << "creating test directory tree in " << _root; - QDir rootDir(_root); - - rootDir.mkpath(_root + "/a1/b1/c1"); - rootDir.mkpath(_root + "/a1/b1/c2"); - rootDir.mkpath(_root + "/a1/b2/c1"); - rootDir.mkpath(_root + "/a1/b3/c3"); - rootDir.mkpath(_root + "/a2/b3/c3"); - Utility::writeRandomFile( _root+"/a1/random.bin"); - Utility::writeRandomFile( _root+"/a1/b2/todelete.bin"); - Utility::writeRandomFile( _root+"/a2/renamefile"); - Utility::writeRandomFile( _root+"/a1/movefile"); - - _watcher = new FolderWatcher(_root); - QObject::connect(_watcher, SIGNAL(pathChanged(QString)), this, SLOT(slotFolderChanged(QString))); - _timer.singleShot(5000, this, SLOT(slotEnd())); + QDir rootDir(_root.path()); + _rootPath = rootDir.canonicalPath(); + qDebug() << "creating test directory tree in " << _rootPath; + + rootDir.mkpath("a1/b1/c1"); + rootDir.mkpath("a1/b1/c2"); + rootDir.mkpath("a1/b2/c1"); + rootDir.mkpath("a1/b3/c3"); + rootDir.mkpath("a2/b3/c3"); + Utility::writeRandomFile( _rootPath+"/a1/random.bin"); + Utility::writeRandomFile( _rootPath+"/a1/b2/todelete.bin"); + Utility::writeRandomFile( _rootPath+"/a2/renamefile"); + Utility::writeRandomFile( _rootPath+"/a1/movefile"); + + _watcher.reset(new FolderWatcher(_rootPath)); + _pathChangedSpy.reset(new QSignalSpy(_watcher.data(), SIGNAL(pathChanged(QString)))); } +private slots: void init() { - _receivedNotifications.clear(); - _requiredNotifications.clear(); - _skipNotifications.clear(); - } - - void checkNotifications() - { - processAndWait(); - QCOMPARE(_receivedNotifications, _requiredNotifications); + _pathChangedSpy->clear(); } void testACreate() { // create a new file - QString file(_root + "/foo.txt"); + QString file(_rootPath + "/foo.txt"); QString cmd; - _requiredNotifications.insert(file); cmd = QString("echo \"xyz\" > %1").arg(file); qDebug() << "Command: " << cmd; system(cmd.toLocal8Bit()); - checkNotifications(); + QVERIFY(waitForPathChanged(file)); } void testATouch() { // touch an existing file. - QString file(_root + "/a1/random.bin"); - _requiredNotifications.insert(file); -#ifdef Q_OS_WIN - Utility::writeRandomFile(QString("%1/a1/random.bin").arg(_root)); -#else - QString cmd; - cmd = QString("touch %1").arg(file); - qDebug() << "Command: " << cmd; - system(cmd.toLocal8Bit()); -#endif - - checkNotifications(); + QString file(_rootPath + "/a1/random.bin"); + touch(file); + QVERIFY(waitForPathChanged(file)); } void testCreateADir() { - QString file(_root+"/a1/b1/new_dir"); - _requiredNotifications.insert(file); - //_skipNotifications.insert(_root + "/a1/b1/new_dir"); - QDir dir; - dir.mkdir(file); - QVERIFY(QFile::exists(file)); - - checkNotifications(); + QString file(_rootPath+"/a1/b1/new_dir"); + mkdir(file); + QVERIFY(waitForPathChanged(file)); } void testRemoveADir() { - QString file(_root+"/a1/b3/c3"); - _requiredNotifications.insert(file); - QDir dir; - QVERIFY(dir.rmdir(file)); - - checkNotifications(); + QString file(_rootPath+"/a1/b3/c3"); + rmdir(file); + QVERIFY(waitForPathChanged(file)); } void testRemoveAFile() { - QString file(_root+"/a1/b2/todelete.bin"); - _requiredNotifications.insert(file); + QString file(_rootPath+"/a1/b2/todelete.bin"); QVERIFY(QFile::exists(file)); - QFile::remove(file); + rm(file); QVERIFY(!QFile::exists(file)); - checkNotifications(); + QVERIFY(waitForPathChanged(file)); } void testRenameAFile() { - QString file1(_root+"/a2/renamefile"); - QString file2(_root+"/a2/renamefile.renamed"); - _requiredNotifications.insert(file1); - _requiredNotifications.insert(file2); + QString file1(_rootPath+"/a2/renamefile"); + QString file2(_rootPath+"/a2/renamefile.renamed"); QVERIFY(QFile::exists(file1)); - QFile::rename(file1, file2); + mv(file1, file2); QVERIFY(QFile::exists(file2)); - checkNotifications(); + QVERIFY(waitForPathChanged(file1)); + QVERIFY(waitForPathChanged(file2)); } void testMoveAFile() { - QString old_file(_root+"/a1/movefile"); - QString new_file(_root+"/a2/movefile.renamed"); - _requiredNotifications.insert(old_file); - _requiredNotifications.insert(new_file); + QString old_file(_rootPath+"/a1/movefile"); + QString new_file(_rootPath+"/a2/movefile.renamed"); QVERIFY(QFile::exists(old_file)); - QFile::rename(old_file, new_file); + mv(old_file, new_file); QVERIFY(QFile::exists(new_file)); - checkNotifications(); - } - - void cleanupTestCase() { - if( _root.startsWith(QDir::tempPath() )) { - system( QString("rm -rf %1").arg(_root).toLocal8Bit() ); - } - delete _watcher; + QVERIFY(waitForPathChanged(old_file)); + QVERIFY(waitForPathChanged(new_file)); } }; @@ -178,6 +191,8 @@ int main(int argc, char *argv[]) TestFolderWatcher tc; return QTest::qExec(&tc, argc, argv); } +#elif defined(Q_OS_MAC) + QTEST_MAIN(TestFolderWatcher) #else QTEST_GUILESS_MAIN(TestFolderWatcher) #endif -- 2.30.2