From 65823eb649bfd0b8a2906d6147238e210682f3c7 Mon Sep 17 00:00:00 2001 From: alex-z Date: Thu, 4 Apr 2024 19:15:53 +0200 Subject: [PATCH] Test file watcher locked & unlocked files detection. Test newly-uploaded office files locked & unlocked files detection. Signed-off-by: alex-z --- src/gui/folderwatcher.h | 2 + test/testfolderwatcher.cpp | 115 +++++++++++++++++++++++++++++++++++++ test/testlockfile.cpp | 21 +++++++ 3 files changed, 138 insertions(+) diff --git a/src/gui/folderwatcher.h b/src/gui/folderwatcher.h index 7591b62627edb..008e312c6fbfa 100644 --- a/src/gui/folderwatcher.h +++ b/src/gui/folderwatcher.h @@ -29,6 +29,7 @@ #include #include +class TestFolderWatcher; namespace OCC { Q_DECLARE_LOGGING_CATEGORY(lcFolderWatcher) @@ -151,6 +152,7 @@ private slots: QTimer _lockChangeDebouncingTimer; friend class FolderWatcherPrivate; + friend class TestFolderWatcher; }; } diff --git a/test/testfolderwatcher.cpp b/test/testfolderwatcher.cpp index d57358d37077a..989beb07aaf4f 100644 --- a/test/testfolderwatcher.cpp +++ b/test/testfolderwatcher.cpp @@ -262,6 +262,121 @@ private slots: mkdir(dir); QVERIFY(waitForPathChanged(dir)); } + + void testDetectLockFiles() + { + QStringList listOfOfficeFiles = {QString(_rootPath + "/document.docx"), QString(_rootPath + "/document.odt")}; + std::sort(std::begin(listOfOfficeFiles), std::end(listOfOfficeFiles)); + + const QStringList listOfOfficeLockFiles = {QString(_rootPath + "/.~lock.document.docx#"), QString(_rootPath + "/.~lock.document.odt#")}; + + _watcher->_shouldWatchForFileUnlocking = true; + + // verify that office files for locking got detected by the watcher + QScopedPointer locksImposedSpy(new QSignalSpy(_watcher.data(), &FolderWatcher::filesLockImposed)); + + for (const auto &officeFile : listOfOfficeFiles) { + touch(officeFile); + QVERIFY(waitForPathChanged(officeFile)); + } + for (const auto &officeLockFile : listOfOfficeLockFiles) { + touch(officeLockFile); + QVERIFY(waitForPathChanged(officeLockFile)); + } + + locksImposedSpy->wait(_watcher->_lockChangeDebouncingTimer.interval() + 100); + QCOMPARE(locksImposedSpy->count(), 1); + auto lockedOfficeFilesByWatcher = locksImposedSpy->takeFirst().at(0).value>().toList(); + std::sort(std::begin(lockedOfficeFilesByWatcher), std::end(lockedOfficeFilesByWatcher)); + QCOMPARE(listOfOfficeFiles.size(), lockedOfficeFilesByWatcher.size()); + + for (int i = 0; i < listOfOfficeFiles.size(); ++i) { + QVERIFY(listOfOfficeFiles.at(i) == lockedOfficeFilesByWatcher.at(i)); + } + + // verify that office files for unlocking got detected by the watcher + QScopedPointer locksReleasedSpy(new QSignalSpy(_watcher.data(), &FolderWatcher::filesLockReleased)); + + for (const auto &officeLockFile : listOfOfficeLockFiles) { + rm(officeLockFile); + QVERIFY(waitForPathChanged(officeLockFile)); + } + + locksReleasedSpy->wait(_watcher->_lockChangeDebouncingTimer.interval() + 100); + QCOMPARE(locksReleasedSpy->count(), 1); + auto unLockedOfficeFilesByWatcher = locksReleasedSpy->takeFirst().at(0).value>().toList(); + std::sort(std::begin(unLockedOfficeFilesByWatcher), std::end(unLockedOfficeFilesByWatcher)); + QCOMPARE(listOfOfficeFiles.size(), unLockedOfficeFilesByWatcher.size()); + + for (int i = 0; i < listOfOfficeFiles.size(); ++i) { + QVERIFY(listOfOfficeFiles.at(i) == unLockedOfficeFilesByWatcher.at(i)); + } + + // cleanup + for (const auto &officeLockFile : listOfOfficeLockFiles) { + rm(officeLockFile); + } + for (const auto &officeFile : listOfOfficeFiles) { + rm(officeFile); + } + } + void testDetectLockFilesExternally() + { + QStringList listOfOfficeFiles = {QString(_rootPath + "/document.docx"), QString(_rootPath + "/document.odt")}; + std::sort(std::begin(listOfOfficeFiles), std::end(listOfOfficeFiles)); + + const QStringList listOfOfficeLockFiles = {QString(_rootPath + "/.~lock.document.docx#"), QString(_rootPath + "/.~lock.document.odt#")}; + + for (const auto &officeFile : listOfOfficeFiles) { + touch(officeFile); + } + for (const auto &officeLockFile : listOfOfficeLockFiles) { + touch(officeLockFile); + } + + _watcher.reset(new FolderWatcher); + _watcher->init(_rootPath); + _watcher->_shouldWatchForFileUnlocking = true; + _pathChangedSpy.reset(new QSignalSpy(_watcher.data(), &FolderWatcher::pathChanged)); + QScopedPointer locksImposedSpy(new QSignalSpy(_watcher.data(), &FolderWatcher::filesLockImposed)); + QScopedPointer locksReleasedSpy(new QSignalSpy(_watcher.data(), &FolderWatcher::filesLockReleased)); + + for (const auto &officeLockFile : listOfOfficeLockFiles) { + _watcher->slotLockFileDetectedExternally(officeLockFile); + } + + // locked files detected + locksImposedSpy->wait(_watcher->_lockChangeDebouncingTimer.interval() + 100); + QCOMPARE(locksImposedSpy->count(), 1); + auto lockedOfficeFilesByWatcher = locksImposedSpy->takeFirst().at(0).value>().toList(); + std::sort(std::begin(lockedOfficeFilesByWatcher), std::end(lockedOfficeFilesByWatcher)); + QCOMPARE(listOfOfficeFiles.size(), lockedOfficeFilesByWatcher.size()); + for (int i = 0; i < listOfOfficeFiles.size(); ++i) { + QVERIFY(listOfOfficeFiles.at(i) == lockedOfficeFilesByWatcher.at(i)); + } + + // unlocked files detected + for (const auto &officeLockFile : listOfOfficeLockFiles) { + rm(officeLockFile); + } + locksReleasedSpy->wait(_watcher->_lockChangeDebouncingTimer.interval() + 100); + QCOMPARE(locksReleasedSpy->count(), 1); + auto unLockedOfficeFilesByWatcher = locksReleasedSpy->takeFirst().at(0).value>().toList(); + std::sort(std::begin(unLockedOfficeFilesByWatcher), std::end(unLockedOfficeFilesByWatcher)); + QCOMPARE(listOfOfficeFiles.size(), unLockedOfficeFilesByWatcher.size()); + + for (int i = 0; i < listOfOfficeFiles.size(); ++i) { + QVERIFY(listOfOfficeFiles.at(i) == unLockedOfficeFilesByWatcher.at(i)); + } + + // cleanup + for (const auto &officeFile : listOfOfficeFiles) { + rm(officeFile); + } + for (const auto &officeLockFile : listOfOfficeLockFiles) { + rm(officeLockFile); + } + } }; #ifdef Q_OS_MAC diff --git a/test/testlockfile.cpp b/test/testlockfile.cpp index 174f9c656abea..bd3680a43ddc3 100644 --- a/test/testlockfile.cpp +++ b/test/testlockfile.cpp @@ -750,6 +750,27 @@ private slots: const auto localFileLocked = QFileInfo{fakeFolder.localPath() + u"A/a1"}; QVERIFY(!localFileLocked.isWritable()); } + + void testLockFile_lockFile_detect_newly_uploaded() + { + const auto testFileName = QStringLiteral("document.docx"); + const auto testLockFileName = QStringLiteral(".~lock.document.docx#"); + + const auto testDocumentsDirName = "documents"; + + FakeFolder fakeFolder{FileInfo{}}; + fakeFolder.localModifier().mkdir(testDocumentsDirName); + + fakeFolder.syncEngine().account()->setCapabilities({{"files", QVariantMap{{"locking", QByteArray{"1.0"}}}}}); + QSignalSpy lockFileDetectedNewlyUploadedSpy(&fakeFolder.syncEngine(), &OCC::SyncEngine::lockFileDetected); + + fakeFolder.localModifier().insert(testDocumentsDirName + QString("/") + testLockFileName); + fakeFolder.localModifier().insert(testDocumentsDirName + QString("/") + testFileName); + + QVERIFY(fakeFolder.syncOnce()); + + QCOMPARE(lockFileDetectedNewlyUploadedSpy.count(), 1); + } }; QTEST_GUILESS_MAIN(TestLockFile)