From 5e91e5052b3b0d0b7fd76855cf32701f49ff736a Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Thu, 4 Sep 2025 13:50:57 +0200 Subject: [PATCH] feat(vfs/windows): default automated tests to VFS mode by default automated tests are done with classic sync on Windows, we will use CfApi VFS plug-in by default to increase test coverage Signed-off-by: Matthieu Gallien --- test/nextcloud_add_test.cmake | 16 ++- test/syncenginetestutils.cpp | 32 ++++-- test/syncenginetestutils.h | 9 +- test/testsynccfapi.cpp | 49 ++------- test/testsyncengine.cpp | 187 +++++++++++++++++++++++++--------- 5 files changed, 195 insertions(+), 98 deletions(-) diff --git a/test/nextcloud_add_test.cmake b/test/nextcloud_add_test.cmake index 489ba31c2587f..1fc1784ef5b63 100644 --- a/test/nextcloud_add_test.cmake +++ b/test/nextcloud_add_test.cmake @@ -100,7 +100,7 @@ macro(nextcloud_add_benchmark test_class) add_executable(${OWNCLOUD_TEST_CLASS}Bench benchmarks/bench${OWNCLOUD_TEST_CLASS_LOWERCASE}.cpp) set_target_properties(${OWNCLOUD_TEST_CLASS}Bench PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}) - target_link_libraries(${OWNCLOUD_TEST_CLASS}Bench + target_link_libraries(${OWNCLOUD_TEST_CLASS}Bench PRIVATE Nextcloud::sync testutils nextcloudCore @@ -112,8 +112,20 @@ macro(nextcloud_add_benchmark test_class) Qt::Core5Compat ) +if (WIN32) + target_link_libraries(${OWNCLOUD_TEST_CLASS}Bench PRIVATE + nextcloudsync_vfs_cfapi + ) +endif() + +if (LINUX) + target_link_libraries(${OWNCLOUD_TEST_CLASS}Bench PRIVATE + nextcloudsync_vfs_xattr + ) +endif() + IF(BUILD_UPDATER) - target_link_libraries(${OWNCLOUD_TEST_CLASS}Bench + target_link_libraries(${OWNCLOUD_TEST_CLASS}Bench PRIVATE updater ) endif() diff --git a/test/syncenginetestutils.cpp b/test/syncenginetestutils.cpp index dc558288d134a..c918d3fdca8bb 100644 --- a/test/syncenginetestutils.cpp +++ b/test/syncenginetestutils.cpp @@ -14,6 +14,10 @@ #include "gui/sharepermissions.h" #include "httplogger.h" +#if defined Q_OS_WINDOWS +#include "vfs/cfapi/cfapiwrapper.h" +#endif + #include #include #include @@ -1217,7 +1221,7 @@ void FakeQNAM::setServerVersion(const QString &version) _serverVersion = version; } -FakeFolder::FakeFolder(const FileInfo &fileTemplate, const OCC::Optional &localFileInfo, const QString &remotePath) +FakeFolder::FakeFolder(const FileInfo &fileTemplate, const OCC::Optional &localFileInfo, const QString &remotePath, OCC::Vfs::Mode vfsMode) : _localModifier(_tempDir.path()) { // Needs to be done once @@ -1253,8 +1257,7 @@ FakeFolder::FakeFolder(const FileInfo &fileTemplate, const OCC::OptionalsyncOptions()._vfs); + setupVfs(vfsMode); // A new folder will update the local file state database on first sync. // To have a state matching what users will encounter, we have to a sync @@ -1417,6 +1420,22 @@ void FakeFolder::execUntilItemCompleted(const QString &relativePath) QVERIFY(false); } +QSharedPointer FakeFolder::setupVfs(OCC::Vfs::Mode vfsMode) +{ + auto vfsPlugin = QSharedPointer(createVfsFromPlugin(vfsMode).release()); + QObject::connect(&syncEngine().syncFileStatusTracker(), &OCC::SyncFileStatusTracker::fileStatusChanged, + vfsPlugin.data(), &OCC::Vfs::fileStatusChanged); + switchToVfs(vfsPlugin); + +#if defined Q_OS_WINDOWS + if (vfsMode == OCC::Vfs::Mode::WindowsCfApi) { + OCC::CfApiWrapper::setPinState(localPath(), OCC::PinState::Unspecified, OCC::CfApiWrapper::NoRecurse); + } +#endif + + return vfsPlugin; +} + void FakeFolder::toDisk(QDir &dir, const FileInfo &templateFi) { for(const auto &child : templateFi.children) { @@ -1447,11 +1466,10 @@ void FakeFolder::fromDisk(QDir &dir, FileInfo &templateFi) QFile f { diskChild.filePath() }; f.open(QFile::ReadOnly); auto content = f.read(1); - if (content.size() == 0) { - qWarning() << "Empty file at:" << diskChild.filePath(); - continue; + auto contentChar = char{}; + if (content.size() > 0) { + contentChar = content.at(0); } - char contentChar = content.at(0); templateFi.children.insert(diskChild.fileName(), FileInfo{diskChild.fileName(), diskChild.size(), contentChar, diskChild.lastModified()}); } } diff --git a/test/syncenginetestutils.h b/test/syncenginetestutils.h index d5db1fbc88669..90fabf1734c59 100644 --- a/test/syncenginetestutils.h +++ b/test/syncenginetestutils.h @@ -11,6 +11,7 @@ #include "account.h" #include "common/result.h" +#include "common/vfs.h" #include "creds/abstractcredentials.h" #include "logger.h" #include "filesystem.h" @@ -579,7 +580,11 @@ class FakeFolder QString _serverVersion = QStringLiteral("10.0.0"); public: - FakeFolder(const FileInfo &fileTemplate, const OCC::Optional &localFileInfo = {}, const QString &remotePath = {}); +#if defined Q_OS_WINDOWS + FakeFolder(const FileInfo &fileTemplate, const OCC::Optional &localFileInfo = {}, const QString &remotePath = {}, OCC::Vfs::Mode vfsMode = OCC::Vfs::Mode::WindowsCfApi); +#else + FakeFolder(const FileInfo &fileTemplate, const OCC::Optional &localFileInfo = {}, const QString &remotePath = {}, OCC::Vfs::Mode vfsMode = OCC::Vfs::Mode::Off); +#endif void switchToVfs(QSharedPointer vfs); @@ -634,6 +639,8 @@ class FakeFolder return execUntilFinished(); } + QSharedPointer setupVfs(OCC::Vfs::Mode vfsMode); + private: static void toDisk(QDir &dir, const FileInfo &templateFi); diff --git a/test/testsynccfapi.cpp b/test/testsynccfapi.cpp index d16832470bedf..807ca33ece508 100644 --- a/test/testsynccfapi.cpp +++ b/test/testsynccfapi.cpp @@ -97,18 +97,6 @@ void markForDehydration(FakeFolder &folder, const QByteArray &path) journal.schedulePathForRemoteDiscovery(record._path); } -QSharedPointer setupVfs(FakeFolder &folder) -{ - auto cfapiVfs = QSharedPointer(createVfsFromPlugin(Vfs::WindowsCfApi).release()); - QObject::connect(&folder.syncEngine().syncFileStatusTracker(), &SyncFileStatusTracker::fileStatusChanged, - cfapiVfs.data(), &Vfs::fileStatusChanged); - folder.switchToVfs(cfapiVfs); - - ::setPinState(folder.localPath(), PinState::Unspecified, cfapi::NoRecurse); - - return cfapiVfs; -} - class TestSyncCfApi : public QObject { Q_OBJECT @@ -133,7 +121,7 @@ private slots: void testReplaceFileByIdenticalFile() { FakeFolder fakeFolder{FileInfo{}}; - auto vfs = setupVfs(fakeFolder); + auto vfs = fakeFolder.syncEngine().syncOptions()._vfs; ItemCompletedSpy completeSpy(fakeFolder); // Create a new local (non-placeholder) file @@ -172,7 +160,7 @@ private slots: void testReplaceOnlineOnlyFile() { FakeFolder fakeFolder{FileInfo{}}; - auto vfs = setupVfs(fakeFolder); + auto vfs = fakeFolder.syncEngine().syncOptions()._vfs; // Create a new local (non-placeholder) file fakeFolder.localModifier().insert("file"); @@ -206,7 +194,6 @@ private slots: QFETCH(bool, doLocalDiscovery); FakeFolder fakeFolder{ FileInfo() }; - setupVfs(fakeFolder); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); ItemCompletedSpy completeSpy(fakeFolder); @@ -335,7 +322,6 @@ private slots: void testVirtualFileConflict() { FakeFolder fakeFolder{ FileInfo() }; - setupVfs(fakeFolder); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); ItemCompletedSpy completeSpy(fakeFolder); @@ -394,7 +380,6 @@ private slots: void testWithNormalSync() { FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; - setupVfs(fakeFolder); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); ItemCompletedSpy completeSpy(fakeFolder); @@ -429,7 +414,6 @@ private slots: void testVirtualFileDownload() { FakeFolder fakeFolder{ FileInfo() }; - setupVfs(fakeFolder); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); ItemCompletedSpy completeSpy(fakeFolder); @@ -531,7 +515,6 @@ private slots: void testVirtualFileDownloadResume() { FakeFolder fakeFolder{ FileInfo() }; - setupVfs(fakeFolder); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); ItemCompletedSpy completeSpy(fakeFolder); @@ -568,7 +551,6 @@ private slots: void testNewFilesNotVirtual() { FakeFolder fakeFolder{ FileInfo() }; - setupVfs(fakeFolder); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); fakeFolder.remoteModifier().mkdir("A"); @@ -588,7 +570,6 @@ private slots: void testDownloadRecursive() { FakeFolder fakeFolder{ FileInfo() }; - setupVfs(fakeFolder); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); // Create a virtual file for remote files @@ -662,7 +643,6 @@ private slots: void testRenameVirtual() { FakeFolder fakeFolder{ FileInfo() }; - setupVfs(fakeFolder); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); ItemCompletedSpy completeSpy(fakeFolder); @@ -711,7 +691,6 @@ private slots: void testRenameVirtual2() { FakeFolder fakeFolder{ FileInfo() }; - setupVfs(fakeFolder); ItemCompletedSpy completeSpy(fakeFolder); auto cleanup = [&]() { completeSpy.clear(); @@ -767,7 +746,6 @@ private slots: fakeFolder.remoteModifier().remove("A/a2"); fakeFolder.remoteModifier().insert("A/a1", 1024 * 1024); fakeFolder.remoteModifier().insert("A/a2", 1024 * 1024); - setupVfs(fakeFolder); QVERIFY(fakeFolder.syncOnce()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); @@ -877,7 +855,6 @@ private slots: // TODO: Part of this test related to A/a3 is always failing on CI but never fails locally // I had to comment it out as this prevents from running all other tests with no working ways to fix that FakeFolder fakeFolder{ FileInfo{} }; - setupVfs(fakeFolder); // Create a suffix-vfs baseline @@ -937,7 +914,6 @@ private slots: void testNewVirtuals() { FakeFolder fakeFolder{ FileInfo() }; - setupVfs(fakeFolder); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); fakeFolder.remoteModifier().mkdir("local"); @@ -1018,7 +994,7 @@ private slots: void testAvailability() { FakeFolder fakeFolder{ FileInfo() }; - auto vfs = setupVfs(fakeFolder); + auto vfs = fakeFolder.syncEngine().syncOptions()._vfs; QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); fakeFolder.remoteModifier().mkdir("local"); @@ -1080,7 +1056,7 @@ private slots: void testPinStateLocals() { FakeFolder fakeFolder{ FileInfo() }; - auto vfs = setupVfs(fakeFolder); + auto vfs = fakeFolder.syncEngine().syncOptions()._vfs; QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); fakeFolder.remoteModifier().mkdir("local"); @@ -1159,7 +1135,6 @@ private slots: void testEmptyFolderInOnlineOnlyRoot() { FakeFolder fakeFolder{ FileInfo() }; - setupVfs(fakeFolder); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); ItemCompletedSpy completeSpy(fakeFolder); @@ -1186,7 +1161,7 @@ private slots: void testIncompatiblePins() { FakeFolder fakeFolder{ FileInfo() }; - auto vfs = setupVfs(fakeFolder); + auto vfs = fakeFolder.syncEngine().syncOptions()._vfs; QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); fakeFolder.remoteModifier().mkdir("local"); @@ -1239,7 +1214,6 @@ private slots: QFETCH(int, errorKind); FakeFolder fakeFolder{ FileInfo() }; - setupVfs(fakeFolder); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); fakeFolder.remoteModifier().mkdir("online"); @@ -1303,7 +1277,6 @@ private slots: void testDataFingerPrint() { FakeFolder fakeFolder{ FileInfo{} }; - setupVfs(fakeFolder); fakeFolder.remoteModifier().mkdir("a"); fakeFolder.remoteModifier().mkdir("a/b"); @@ -1329,7 +1302,6 @@ private slots: void testLockFile_lockedFileReadOnly_afterSync() { FakeFolder fakeFolder{ FileInfo{} }; - setupVfs(fakeFolder); ItemCompletedSpy completeSpy(fakeFolder); @@ -1368,7 +1340,7 @@ private slots: void testLinkFileDownload() { FakeFolder fakeFolder{FileInfo{}}; - auto vfs = setupVfs(fakeFolder); + auto vfs = fakeFolder.syncEngine().syncOptions()._vfs; qInfo("Starting .lnk test. It might hand and will get killed after timeout..."); @@ -1415,7 +1387,7 @@ private slots: void testFolderDoesNotUpdatePlaceholderMetadata() { FakeFolder fakeFolder{FileInfo{}}; - auto vfs = setupVfs(fakeFolder); + auto vfs = fakeFolder.syncEngine().syncOptions()._vfs; fakeFolder.remoteModifier().mkdir("A"); fakeFolder.remoteModifier().insert("A/file"); @@ -1429,7 +1401,6 @@ private slots: void testRemoteTypeChangeExistingLocalMustGetRemoved() { FakeFolder fakeFolder{FileInfo{}}; - setupVfs(fakeFolder); // test file change to directory on remote fakeFolder.remoteModifier().mkdir("a"); @@ -1457,7 +1428,7 @@ private slots: QSKIP("not applicable"); #endif FakeFolder fakeFolder{FileInfo{}}; - auto vfs = setupVfs(fakeFolder); + auto vfs = fakeFolder.syncEngine().syncOptions()._vfs; QVERIFY(fakeFolder.syncOnce()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); @@ -1492,7 +1463,7 @@ private slots: void renameOnBothSides() { FakeFolder fakeFolder { FileInfo::A12_B12_C12_S12() }; - auto vfs = setupVfs(fakeFolder); + auto vfs = fakeFolder.syncEngine().syncOptions()._vfs; // Test that renaming a file within a directory that was renamed on the other side actually do a rename. @@ -1521,7 +1492,7 @@ private slots: void createFolderAndFiles() { FakeFolder fakeFolder {FileInfo{}}; - auto vfs = setupVfs(fakeFolder); + auto vfs = fakeFolder.syncEngine().syncOptions()._vfs; fakeFolder.remoteModifier().mkdir("first folder"); diff --git a/test/testsyncengine.cpp b/test/testsyncengine.cpp index c585ac61855d9..67c5b32d65cf6 100644 --- a/test/testsyncengine.cpp +++ b/test/testsyncengine.cpp @@ -114,7 +114,10 @@ private slots: fakeFolder.remoteModifier().insert("A/a0"); fakeFolder.syncOnce(); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "A/a0")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testFileUpload() { @@ -123,7 +126,9 @@ private slots: fakeFolder.localModifier().insert("A/a0"); fakeFolder.syncOnce(); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "A/a0")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testDirDownload() { @@ -136,7 +141,9 @@ private slots: QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Y")); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Z")); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Z/d0")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testDirUpload() { @@ -149,7 +156,9 @@ private slots: QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Y")); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Z")); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Z/d0")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testDirUploadWithDelayedAlgorithm() { @@ -182,7 +191,9 @@ private slots: QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "r0") > 1); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "r1")); QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "r1") > 1); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testDirUploadWithDelayedAlgorithmWithNewChecksum() { @@ -216,7 +227,9 @@ private slots: QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "r0") > 1); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "r1")); QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "r1") > 1); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } @@ -240,7 +253,9 @@ private slots: fakeFolder.remoteModifier().remove("A/a1"); fakeFolder.syncOnce(); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "A/a1")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testRemoteDelete() { @@ -249,7 +264,9 @@ private slots: fakeFolder.localModifier().remove("A/a1"); fakeFolder.syncOnce(); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "A/a1")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testLocalDeleteWithReuploadForNewLocalFiles_data() @@ -352,7 +369,9 @@ private slots: QVERIFY(!itemDidComplete(completeSpy, "a1.eml")); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "a2.eml")); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "a3.eml")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testSelectiveSyncBug() { @@ -379,7 +398,9 @@ private slots: }} }}}; - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } auto expectedServerState = fakeFolder.currentRemoteState(); // Remove subFolderA with selectiveSync: @@ -441,7 +462,7 @@ private slots: /** Verify that an incompletely propagated directory doesn't have the server's * etag stored in the database yet. */ void testDirEtagAfterIncompleteSync() { - FakeFolder fakeFolder{FileInfo{}}; + FakeFolder fakeFolder{FileInfo{}, {}, {}, OCC::Vfs::Mode::Off}; QSignalSpy finishedSpy(&fakeFolder.syncEngine(), &SyncEngine::finished); fakeFolder.serverErrorPaths().append("NewFolder/foo"); fakeFolder.remoteModifier().mkdir("NewFolder"); @@ -455,7 +476,7 @@ private slots: } void testDirDownloadWithError() { - FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()}; + FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12(), {}, {}, OCC::Vfs::Mode::Off}; ItemCompletedSpy completeSpy(fakeFolder); fakeFolder.remoteModifier().mkdir("Y"); fakeFolder.remoteModifier().mkdir("Y/Z"); @@ -707,7 +728,7 @@ private slots: // Checks whether downloads with bad checksums are accepted void testChecksumValidation() { - FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; + FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12(), {}, {}, OCC::Vfs::Mode::Off}; QObject parent; QByteArray checksumValue; @@ -739,7 +760,9 @@ private slots: // Basic case fakeFolder.remoteModifier().create("A/a3", 16, 'A'); QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } // Bad OC-Checksum checksumValue = "SHA1:bad"; @@ -752,7 +775,9 @@ private slots: // Good OC-Checksum checksumValue = matchedSha1Checksum; // printf 'A%.0s' {1..16} | sha1sum - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } checksumValue = QByteArray(); // Bad Content-MD5 @@ -763,7 +788,9 @@ private slots: // Good Content-MD5 contentMd5Value = "d8a73157ce10cd94a91c2079fc9a92c8"; // printf 'A%.0s' {1..16} | md5sum - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } // Invalid OC-Checksum is ignored checksumValue = "garbage"; @@ -775,7 +802,9 @@ private slots: QVERIFY(!fakeFolder.syncOnce()); contentMd5Value.clear(); QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } // OC-Checksum contains Unsupported checksums checksumValue = "Unsupported:XXXX SHA1:invalid Invalid:XxX"; @@ -783,7 +812,9 @@ private slots: QVERIFY(!fakeFolder.syncOnce()); // Since the supported SHA1 checksum is invalid, no download checksumValue = "Unsupported:XXXX SHA1:19b1928d58a2030d08023f3d7054516dbc186f20 Invalid:XxX"; QVERIFY(fakeFolder.syncOnce()); // The supported SHA1 checksum is valid now, so the file are downloaded - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } // Begin Test mismatch recalculation--------------------------------------------------------------------------------- @@ -808,7 +839,9 @@ private slots: checksumValue = mismatchedSha1Checksum; checksumValueRecalculated = matchedSha1Checksum; QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } checksumValue = QByteArray(); fakeFolder.account()->setServerVersion(prevServerVersion); @@ -825,7 +858,9 @@ private slots: fakeFolder.syncEngine().account()->setServerVersion("10.0.0"); fakeFolder.localModifier().insert("A/\\:?*\"<>|.txt"); QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } // For legacy servers, some characters were forbidden by the client fakeFolder.syncEngine().account()->setServerVersion("8.0.0"); @@ -837,7 +872,9 @@ private slots: // We can override that by setting the capability fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ { "invalidFilenameRegex", "" } } } }); QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } // Check that new servers also accept the capability fakeFolder.syncEngine().account()->setServerVersion("10.0.0"); @@ -851,7 +888,9 @@ private slots: { FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } // We can't depend on currentLocalState for hidden files since // it should rightfully skip things like download temporaries @@ -882,7 +921,9 @@ private slots: FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } // Utf8 locale can sync both fakeFolder.remoteModifier().insert("A/tößt"); @@ -994,7 +1035,9 @@ private slots: fakeFolder.remoteModifier().mkdir("foo"); QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } QVERIFY(fakeFolder.currentLocalState().find("foo")); @@ -1011,7 +1054,9 @@ private slots: fakeFolder.remoteModifier().find("foo")->lastModified = datetime; QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } QCOMPARE(QFileInfo(fakeFolder.localPath() + "foo").lastModified(), datetime); } @@ -1033,7 +1078,9 @@ private slots: const auto expectedMtime = localFileInfo.metadataChangeTime(); QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } const auto currentMtime = localFileInfo.metadataChangeTime(); QCOMPARE(currentMtime, expectedMtime); @@ -1186,7 +1233,9 @@ private slots: QVERIFY(fakeFolder.syncOnce()); QCOMPARE(nPUT, 9); QCOMPARE(nPOST, 0); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testNetworkErrorsWithSmallerBatchSizes() @@ -1283,7 +1332,9 @@ private slots: QVERIFY(fakeFolder.syncOnce()); QVERIFY(fakeFolder.currentLocalState().find("big_shared_folder/shared_files/big_shared_file_A.data")); QVERIFY(fakeFolder.currentLocalState().find("big_shared_folder/shared_files/big_shared_file_B.data")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } // try to move from a big shared folder to your own folder fakeFolder.localModifier().mkdir("own_folder"); @@ -1315,7 +1366,9 @@ private slots: QVERIFY(!fakeFolder.currentLocalState().find("own_folder/big_shared_file_A.data")); QVERIFY(!fakeFolder.currentLocalState().find("own_folder/big_shared_file_B.data")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testRemoteMoveFailedForbiddenLocalMoveRolledBack() @@ -1332,7 +1385,9 @@ private slots: QVERIFY(fakeFolder.syncOnce()); QVERIFY(fakeFolder.currentLocalState().find("big_shared_folder/shared_files/big_shared_file_A.data")); QVERIFY(fakeFolder.currentLocalState().find("big_shared_folder/shared_files/big_shared_file_B.data")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } // try to move from a big shared folder to your own folder fakeFolder.localModifier().mkdir("own_folder"); @@ -1366,12 +1421,14 @@ private slots: QVERIFY(!fakeFolder.currentLocalState().find("own_folder/big_shared_file_A.data")); QVERIFY(!fakeFolder.currentLocalState().find("own_folder/big_shared_file_B.data")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testFolderWithFilesInError() { - FakeFolder fakeFolder{FileInfo{}}; + FakeFolder fakeFolder{FileInfo{}, {}, {}, OCC::Vfs::Mode::Off}; fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData) -> QNetworkReply * { Q_UNUSED(outgoingData) @@ -1403,7 +1460,9 @@ private slots: constexpr auto CURRENT_MTIME = 1646057277; FakeFolder fakeFolder{FileInfo{}}; - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } const QString fooFileRootFolder("foo"); const QString barFileRootFolder("bar"); @@ -1436,7 +1495,9 @@ private slots: QVERIFY(fakeFolder.syncOnce()); auto expectedState = fakeFolder.currentLocalState(); - QCOMPARE(fakeFolder.currentRemoteState(), expectedState); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentRemoteState(), expectedState); + } } void testInvalidMtimeRecovery() @@ -1445,7 +1506,9 @@ private slots: constexpr auto CURRENT_MTIME = 1646057277; FakeFolder fakeFolder{FileInfo{}}; - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } const QString fooFileRootFolder("foo"); const QString barFileRootFolder("bar"); @@ -1481,7 +1544,9 @@ private slots: QVERIFY(fakeFolder.syncOnce()); auto expectedState = fakeFolder.currentLocalState(); - QCOMPARE(fakeFolder.currentRemoteState(), expectedState); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentRemoteState(), expectedState); + } } void testLocalInvalidMtimeCorrection() @@ -1490,7 +1555,9 @@ private slots: const auto RECENT_MTIME = QDateTime::fromSecsSinceEpoch(1743004783); // 2025-03-26T16:59:43+0100 FakeFolder fakeFolder{FileInfo{}}; - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } fakeFolder.localModifier().insert(QStringLiteral("invalid")); fakeFolder.localModifier().setModTime("invalid", INVALID_MTIME); @@ -1513,7 +1580,9 @@ private slots: // verify that the mtime of "invalid" hasn't changed since the last sync that fixed it QCOMPARE(fakeFolder.currentLocalState().find("invalid")->lastModified, currentMtime); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testLocalInvalidMtimeCorrectionBulkUpload() @@ -1524,7 +1593,9 @@ private slots: const auto RECENT_MTIME = QDateTime::fromSecsSinceEpoch(1743004783); // 2025-03-26T16:59:43+0100 FakeFolder fakeFolder{FileInfo{}}; - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ {"bulkupload", "1.0"} } } }); fakeFolder.localModifier().insert(QStringLiteral("invalid")); @@ -1548,7 +1619,9 @@ private slots: // verify that the mtime of "invalid" hasn't changed since the last sync that fixed it QCOMPARE(fakeFolder.currentLocalState().find("invalid")->lastModified, currentMtime); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testServerUpdatingMTimeShouldNotCreateConflicts() @@ -1564,7 +1637,9 @@ private slots: fakeFolder.syncEngine().setLocalDiscoveryOptions(OCC::LocalDiscoveryStyle::DatabaseAndFilesystem); QVERIFY(fakeFolder.syncOnce()); auto localState = fakeFolder.currentLocalState(); - QCOMPARE(localState, fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(localState, fakeFolder.currentRemoteState()); + } QCOMPARE(printDbData(fakeFolder.dbState()), printDbData(fakeFolder.currentRemoteState())); const auto fileFirstSync = localState.find(testFile); @@ -1576,7 +1651,9 @@ private slots: fakeFolder.syncEngine().setLocalDiscoveryOptions(OCC::LocalDiscoveryStyle::FilesystemOnly); QVERIFY(fakeFolder.syncOnce()); localState = fakeFolder.currentLocalState(); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } QCOMPARE(printDbData(fakeFolder.dbState()), printDbData(fakeFolder.currentRemoteState())); const auto fileSecondSync = localState.find(testFile); QVERIFY(fileSecondSync); @@ -1616,7 +1693,9 @@ private slots: fakeFolder.remoteModifier().insert("A/file"); QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } fakeFolder.remoteModifier().insert("A/FILE"); QVERIFY(fakeFolder.syncOnce()); @@ -1640,7 +1719,7 @@ private slots: constexpr auto shouldHaveCaseClashConflict = true; #endif - FakeFolder fakeFolder{ FileInfo{} }; + FakeFolder fakeFolder{FileInfo{}}; fakeFolder.remoteModifier().insert("otherFile.txt"); fakeFolder.remoteModifier().insert(testLowerCaseFile); @@ -2137,7 +2216,9 @@ private slots: fakeFolder.remoteModifier().insert("A/abcdęfg.txt"); fakeFolder.syncOnce(); QVERIFY(itemDidCompleteSuccessfully(completeSpy, "A/abcdęfg.txt")); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testRemoteTypeChangeExistingLocalMustGetRemoved() @@ -2152,7 +2233,9 @@ private slots: fakeFolder.remoteModifier().remove("a/TESTFILE"); fakeFolder.remoteModifier().mkdir("a/TESTFILE"); QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } // test directory change to file on remote fakeFolder.remoteModifier().mkdir("a/TESTDIR"); @@ -2161,7 +2244,9 @@ private slots: fakeFolder.remoteModifier().remove("a/TESTDIR"); fakeFolder.remoteModifier().insert("a/TESTDIR"); QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } } void testRemoveAllFilesWithNextcloudCmd() @@ -2217,7 +2302,9 @@ private slots: fakeFolder.remoteModifier().insert("file3"); QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } fakeFolder.remoteModifier().remove("folder"); fakeFolder.remoteModifier().remove("folder2"); @@ -2351,7 +2438,9 @@ private slots: fakeFolder.syncEngine().setLocalDiscoveryEnforceWindowsFileNameCompatibility(true); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + if (fakeFolder.syncEngine().syncOptions()._vfs->mode() == Vfs::Mode::Off) { + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } const QString fileWithSpaces1(" foo"); const QString fileWithSpaces2(" bar ");