diff options
author | Christian Kamm <mail@ckamm.de> | 2018-08-15 11:46:16 +0300 |
---|---|---|
committer | Christian Kamm <mail@ckamm.de> | 2018-11-26 14:53:30 +0300 |
commit | 06928a40377deeb5053365e88d805f753bf478f2 (patch) | |
tree | 2b37ed68aa4e8a58b02cd6e2e805f446ebabffb7 /test | |
parent | 96df14f897ebf4fb1f423149cba9f2972e5f280d (diff) |
winvfs: initial work
Done by ckamm and dschmidt
Diffstat (limited to 'test')
-rw-r--r-- | test/owncloud_add_test.cmake | 7 | ||||
-rw-r--r-- | test/syncenginetestutils.h | 1 | ||||
-rw-r--r-- | test/testsyncvirtualfiles.cpp | 207 |
3 files changed, 168 insertions, 47 deletions
diff --git a/test/owncloud_add_test.cmake b/test/owncloud_add_test.cmake index ee2cfd200..c28101939 100644 --- a/test/owncloud_add_test.cmake +++ b/test/owncloud_add_test.cmake @@ -16,7 +16,12 @@ macro(owncloud_add_test test_class additional_cpp) add_definitions(-DOWNCLOUD_TEST) add_definitions(-DOWNCLOUD_BIN_PATH="${CMAKE_BINARY_DIR}/bin") - add_test(NAME ${OWNCLOUD_TEST_CLASS}Test COMMAND ${OWNCLOUD_TEST_CLASS}Test) + message(STATUS "Add test: ${OWNCLOUD_TEST_CLASS}Test") + add_test(NAME ${OWNCLOUD_TEST_CLASS}Test + COMMAND ${OWNCLOUD_TEST_CLASS}Test + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/bin") + + target_include_directories(${OWNCLOUD_TEST_CLASS}Test PRIVATE "${CMAKE_SOURCE_DIR}/test/") endmacro() macro(owncloud_add_benchmark test_class additional_cpp) diff --git a/test/syncenginetestutils.h b/test/syncenginetestutils.h index 48a380d5e..44f117b06 100644 --- a/test/syncenginetestutils.h +++ b/test/syncenginetestutils.h @@ -1145,6 +1145,7 @@ public: syncOnce(); } + OCC::AccountPtr account() const { return _account; } OCC::SyncEngine &syncEngine() const { return *_syncEngine; } OCC::SyncJournalDb &syncJournal() const { return *_journalDb; } diff --git a/test/testsyncvirtualfiles.cpp b/test/testsyncvirtualfiles.cpp index 7a3964c4d..2a5d2326e 100644 --- a/test/testsyncvirtualfiles.cpp +++ b/test/testsyncvirtualfiles.cpp @@ -7,6 +7,8 @@ #include <QtTest> #include "syncenginetestutils.h" +#include "common/vfs.h" +#include "plugin.h" #include <syncengine.h> using namespace OCC; @@ -46,6 +48,25 @@ void triggerDownload(FakeFolder &folder, const QByteArray &path) journal.avoidReadFromDbOnNextSync(record._path); } +void markForDehydration(FakeFolder &folder, const QByteArray &path) +{ + auto &journal = folder.syncJournal(); + SyncJournalFileRecord record; + journal.getFileRecord(path, &record); + if (!record.isValid()) + return; + record._type = ItemTypeVirtualFileDehydration; + journal.setFileRecord(record); + journal.avoidReadFromDbOnNextSync(record._path); +} + +SyncOptions vfsSyncOptions() +{ + SyncOptions options; + options._vfs = PluginLoader().create<Vfs>("vfs", "suffix"); + return options; +} + class TestSyncVirtualFiles : public QObject { Q_OBJECT @@ -64,9 +85,7 @@ private slots: QFETCH(bool, doLocalDiscovery); FakeFolder fakeFolder{ FileInfo() }; - SyncOptions syncOptions; - syncOptions._newFilesAreVirtual = true; - fakeFolder.syncEngine().setSyncOptions(syncOptions); + fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &))); @@ -187,9 +206,7 @@ private slots: void testVirtualFileConflict() { FakeFolder fakeFolder{ FileInfo() }; - SyncOptions syncOptions; - syncOptions._newFilesAreVirtual = true; - fakeFolder.syncEngine().setSyncOptions(syncOptions); + fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &))); @@ -260,9 +277,7 @@ private slots: void testWithNormalSync() { FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; - SyncOptions syncOptions; - syncOptions._newFilesAreVirtual = true; - fakeFolder.syncEngine().setSyncOptions(syncOptions); + fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &))); @@ -298,9 +313,7 @@ private slots: void testVirtualFileDownload() { FakeFolder fakeFolder{ FileInfo() }; - SyncOptions syncOptions; - syncOptions._newFilesAreVirtual = true; - fakeFolder.syncEngine().setSyncOptions(syncOptions); + fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &))); @@ -368,9 +381,7 @@ private slots: void testVirtualFileDownloadResume() { FakeFolder fakeFolder{ FileInfo() }; - SyncOptions syncOptions; - syncOptions._newFilesAreVirtual = true; - fakeFolder.syncEngine().setSyncOptions(syncOptions); + fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &))); @@ -408,13 +419,12 @@ private slots: QVERIFY(!dbRecord(fakeFolder, "A/a1.owncloud").isValid()); } - // Check what might happen if an older sync client encounters virtual files - void testOldVersion1() + // Check what happens if vfs mode is disabled + void testSwitchOfVfs() { QSKIP("Does not work with the new discovery because the way we simulate the old client does not work"); FakeFolder fakeFolder{ FileInfo() }; - SyncOptions syncOptions; - syncOptions._newFilesAreVirtual = true; + SyncOptions syncOptions = vfsSyncOptions(); fakeFolder.syncEngine().setSyncOptions(syncOptions); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); @@ -424,30 +434,20 @@ private slots: QVERIFY(fakeFolder.syncOnce()); QVERIFY(fakeFolder.currentLocalState().find("A/a1.owncloud")); - // Simulate an old client by switching the type of all ItemTypeVirtualFile - // entries in the db to an invalid type. - auto &db = fakeFolder.syncJournal(); - SyncJournalFileRecord rec; - db.getFileRecord(QByteArray("A/a1.owncloud"), &rec); - QVERIFY(rec.isValid()); - QCOMPARE(rec._type, ItemTypeVirtualFile); - rec._type = static_cast<ItemType>(-1); - db.setFileRecord(rec); - - // Also switch off new files becoming virtual files - syncOptions._newFilesAreVirtual = false; + // Switch off new files becoming virtual files + syncOptions._vfs = nullptr; fakeFolder.syncEngine().setSyncOptions(syncOptions); - // A sync that doesn't do remote discovery has no effect + // A sync that doesn't do remote discovery will wipe the placeholder, but not redownload QVERIFY(fakeFolder.syncOnce()); - QVERIFY(fakeFolder.currentLocalState().find("A/a1.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/a1.owncloud")); QVERIFY(!fakeFolder.currentLocalState().find("A/a1")); QVERIFY(fakeFolder.currentRemoteState().find("A/a1")); QVERIFY(!fakeFolder.currentRemoteState().find("A/a1.owncloud")); // But with a remote discovery the virtual files will be removed and // the remote files will be downloaded. - db.forceRemoteDiscoveryNextSync(); + fakeFolder.syncJournal().forceRemoteDiscoveryNextSync(); QVERIFY(fakeFolder.syncOnce()); QVERIFY(fakeFolder.currentLocalState().find("A/a1")); QVERIFY(!fakeFolder.currentLocalState().find("A/a1.owncloud")); @@ -477,9 +477,7 @@ private slots: rec._path = "A/a1.owncloud"; db.setFileRecord(rec); - SyncOptions syncOptions; - syncOptions._newFilesAreVirtual = true; - fakeFolder.syncEngine().setSyncOptions(syncOptions); + fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions()); // Check that a sync removes the virtual file and its db entry QVERIFY(fakeFolder.syncOnce()); @@ -491,9 +489,7 @@ private slots: void testDownloadRecursive() { FakeFolder fakeFolder{ FileInfo() }; - SyncOptions syncOptions; - syncOptions._newFilesAreVirtual = true; - fakeFolder.syncEngine().setSyncOptions(syncOptions); + fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); // Create a virtual file for remote files @@ -590,9 +586,7 @@ private slots: void testRenameToVirtual() { FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; - SyncOptions syncOptions; - syncOptions._newFilesAreVirtual = true; - fakeFolder.syncEngine().setSyncOptions(syncOptions); + fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &))); @@ -630,9 +624,7 @@ private slots: void testRenameVirtual() { FakeFolder fakeFolder{ FileInfo() }; - SyncOptions syncOptions; - syncOptions._newFilesAreVirtual = true; - fakeFolder.syncEngine().setSyncOptions(syncOptions); + fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &))); @@ -669,6 +661,129 @@ private slots: QVERIFY(itemInstruction(completeSpy, "file2", CSYNC_INSTRUCTION_NEW)); QVERIFY(dbRecord(fakeFolder, "file2").isValid()); } + + // Dehydration via sync works + void testSyncDehydration() + { + FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; + fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions()); + + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + + QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &))); + auto cleanup = [&]() { + completeSpy.clear(); + }; + cleanup(); + + // + // Mark for dehydration and check + // + + markForDehydration(fakeFolder, "A/a1"); + + markForDehydration(fakeFolder, "A/a2"); + fakeFolder.remoteModifier().appendByte("A/a2"); + // expect: normal dehydration + + markForDehydration(fakeFolder, "B/b1"); + fakeFolder.remoteModifier().remove("B/b1"); + // expect: local removal + + markForDehydration(fakeFolder, "B/b2"); + fakeFolder.remoteModifier().rename("B/b2", "B/b3"); + // expect: B/b2 is gone, B/b3 is NEW placeholder + + markForDehydration(fakeFolder, "C/c1"); + fakeFolder.localModifier().appendByte("C/c1"); + // expect: no dehydration, upload of c1 + + markForDehydration(fakeFolder, "C/c2"); + fakeFolder.localModifier().appendByte("C/c2"); + fakeFolder.remoteModifier().appendByte("C/c2"); + fakeFolder.remoteModifier().appendByte("C/c2"); + // expect: no dehydration, conflict + + QVERIFY(fakeFolder.syncOnce()); + + auto isDehydrated = [&](const QString &path) { + QString placeholder = path + ".owncloud"; + return !fakeFolder.currentLocalState().find(path) + && fakeFolder.currentLocalState().find(placeholder); + }; + + QVERIFY(isDehydrated("A/a1")); + QVERIFY(isDehydrated("A/a2")); + + QVERIFY(!fakeFolder.currentLocalState().find("B/b1")); + QVERIFY(!fakeFolder.currentRemoteState().find("B/b1")); + QVERIFY(itemInstruction(completeSpy, "B/b1", CSYNC_INSTRUCTION_REMOVE)); + + QVERIFY(!fakeFolder.currentLocalState().find("B/b2")); + QVERIFY(!fakeFolder.currentRemoteState().find("B/b2")); + QVERIFY(isDehydrated("B/b3")); + QVERIFY(itemInstruction(completeSpy, "B/b2", CSYNC_INSTRUCTION_REMOVE)); + QVERIFY(itemInstruction(completeSpy, "B/b3.owncloud", CSYNC_INSTRUCTION_NEW)); + + QCOMPARE(fakeFolder.currentRemoteState().find("C/c1")->size, 25); + QVERIFY(itemInstruction(completeSpy, "C/c1", CSYNC_INSTRUCTION_SYNC)); + + QCOMPARE(fakeFolder.currentRemoteState().find("C/c2")->size, 26); + QVERIFY(itemInstruction(completeSpy, "C/c2", CSYNC_INSTRUCTION_CONFLICT)); + cleanup(); + + auto expectedLocalState = fakeFolder.currentLocalState(); + auto expectedRemoteState = fakeFolder.currentRemoteState(); + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(fakeFolder.currentLocalState(), expectedLocalState); + QCOMPARE(fakeFolder.currentRemoteState(), expectedRemoteState); + } + + void testWipeVirtualSuffixFiles() + { + FakeFolder fakeFolder{ FileInfo{} }; + fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions()); + + // Create a suffix-vfs baseline + + fakeFolder.remoteModifier().mkdir("A"); + fakeFolder.remoteModifier().mkdir("A/B"); + fakeFolder.remoteModifier().insert("f1"); + fakeFolder.remoteModifier().insert("A/a1"); + fakeFolder.remoteModifier().insert("A/a3"); + fakeFolder.remoteModifier().insert("A/B/b1"); + fakeFolder.localModifier().mkdir("A"); + fakeFolder.localModifier().mkdir("A/B"); + fakeFolder.localModifier().insert("f2"); + fakeFolder.localModifier().insert("A/a2"); + fakeFolder.localModifier().insert("A/B/b2"); + + QVERIFY(fakeFolder.syncOnce()); + + QVERIFY(fakeFolder.currentLocalState().find("f1.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/a1.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/a3.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/B/b1.owncloud")); + + // Make local changes to a3 + fakeFolder.localModifier().remove("A/a3.owncloud"); + fakeFolder.localModifier().insert("A/a3.owncloud", 100); + + // Now wipe the virtuals + + SyncEngine::wipeVirtualFiles(fakeFolder.localPath(), fakeFolder.syncJournal(), fakeFolder.syncEngine().syncOptions()._vfs); + + QVERIFY(!fakeFolder.currentLocalState().find("f1.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/a1.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/a3.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/B/b1.owncloud")); + + fakeFolder.syncEngine().setSyncOptions(SyncOptions{}); + QVERIFY(fakeFolder.syncOnce()); + QVERIFY(fakeFolder.currentRemoteState().find("A/a3.owncloud")); // regular upload + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } }; QTEST_GUILESS_MAIN(TestSyncVirtualFiles) |