Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gui/folder.cpp2
-rw-r--r--src/libsync/syncjournaldb.cpp11
-rw-r--r--src/libsync/syncjournaldb.h7
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/testallfilesdeleted.cpp118
5 files changed, 138 insertions, 1 deletions
diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp
index 845b5b68d..3bfb54cb0 100644
--- a/src/gui/folder.cpp
+++ b/src/gui/folder.cpp
@@ -908,7 +908,7 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, bool *cancel
}
*cancel = msgBox.clickedButton() == keepBtn;
if (*cancel) {
- wipe();
+ journalDb()->clearFileTable();
_lastEtag.clear();
slotScheduleThisFolder();
}
diff --git a/src/libsync/syncjournaldb.cpp b/src/libsync/syncjournaldb.cpp
index 7ee83db46..43ef9b37a 100644
--- a/src/libsync/syncjournaldb.cpp
+++ b/src/libsync/syncjournaldb.cpp
@@ -1836,6 +1836,17 @@ void SyncJournalDb::setDataFingerprint(const QByteArray &dataFingerprint)
}
}
+void SyncJournalDb::clearFileTable()
+{
+ SqlQuery query(_db);
+ query.prepare("DELETE FROM metadata;");
+ if (!query.exec()) {
+ qWarning() << "SQL error in clearFileTable" << query.error();
+ } else {
+ qDebug() << query.lastQuery() << "(" << query.numRowsAffected() << " rows)";
+ }
+}
+
void SyncJournalDb::commit(const QString& context, bool startTrans)
{
QMutexLocker lock(&_mutex);
diff --git a/src/libsync/syncjournaldb.h b/src/libsync/syncjournaldb.h
index fe00051a3..cd4572644 100644
--- a/src/libsync/syncjournaldb.h
+++ b/src/libsync/syncjournaldb.h
@@ -173,6 +173,13 @@ public:
void setDataFingerprint(const QByteArray &dataFingerprint);
QByteArray dataFingerprint();
+ /**
+ * Delete any file entry. This will force the next sync to re-sync everything as if it was new,
+ * restoring everyfile on every remote. If a file is there both on the client and server side,
+ * it will be a conflict that will be automatically resolved if the file is the same.
+ */
+ void clearFileTable();
+
private:
bool updateDatabaseStructure();
bool updateMetadataTableStructure();
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 16b4b6589..2f94501ee 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -40,6 +40,7 @@ if(HAVE_QT5 AND NOT BUILD_WITH_QT4)
owncloud_add_test(SyncFileStatusTracker "syncenginetestutils.h")
owncloud_add_test(ChunkingNg "syncenginetestutils.h")
owncloud_add_test(UploadReset "syncenginetestutils.h")
+ owncloud_add_test(AllFilesDeleted "syncenginetestutils.h")
owncloud_add_test(FolderWatcher "${FolderWatcher_SRC}")
if( UNIX AND NOT APPLE )
diff --git a/test/testallfilesdeleted.cpp b/test/testallfilesdeleted.cpp
new file mode 100644
index 000000000..d9356c844
--- /dev/null
+++ b/test/testallfilesdeleted.cpp
@@ -0,0 +1,118 @@
+/*
+ * This software is in the public domain, furnished "as is", without technical
+ * support, and with no warranty, express or implied, as to its usefulness for
+ * any purpose.
+ *
+ */
+
+#include <QtTest>
+#include "syncenginetestutils.h"
+#include <syncengine.h>
+
+using namespace OCC;
+
+/*
+ * This test ensure that the SyncEngine::aboutToRemoveAllFiles is correctly called and that when
+ * we the user choose to remove all files SyncJournalDb::clearFileTable makes works as expected
+ */
+class TestAllFilesDeleted : public QObject
+{
+ Q_OBJECT
+
+private slots:
+
+ void testAllFilesDeletedKeep_data()
+ {
+ QTest::addColumn<bool>("deleteOnRemote");
+ QTest::newRow("local") << false;
+ QTest::newRow("remote") << true;
+
+ }
+
+ /*
+ * In this test, all files are deleted in the client, or the server, and we simulate
+ * that the users press "keep"
+ */
+ void testAllFilesDeletedKeep()
+ {
+ QFETCH(bool, deleteOnRemote);
+ FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
+
+ //Just set a blacklist so we can check it is still there. This directory does not exists but
+ // that does not matter for our purposes.
+ QStringList selectiveSyncBlackList = { "Q/" };
+ fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
+ selectiveSyncBlackList);
+
+ auto initialState = fakeFolder.currentLocalState();
+ int aboutToRemoveAllFilesCalled = 0;
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveAllFiles,
+ [&](SyncFileItem::Direction dir, bool *cancel) {
+ QCOMPARE(aboutToRemoveAllFilesCalled, 0);
+ aboutToRemoveAllFilesCalled++;
+ QCOMPARE(dir, deleteOnRemote ? SyncFileItem::Down : SyncFileItem::Up);
+ *cancel = true;
+ fakeFolder.syncEngine().journal()->clearFileTable(); // That's what Folder is doing
+ });
+
+ auto &modifier = deleteOnRemote ? fakeFolder.remoteModifier() : fakeFolder.localModifier();
+ for (const auto &s : fakeFolder.currentRemoteState().children.keys())
+ modifier.remove(s);
+
+ QVERIFY(!fakeFolder.syncOnce()); // Should fail because we cancel the sync
+ QCOMPARE(aboutToRemoveAllFilesCalled, 1);
+
+ // Next sync should recover all files
+ QVERIFY(fakeFolder.syncOnce());
+ QCOMPARE(fakeFolder.currentLocalState(), initialState);
+ QCOMPARE(fakeFolder.currentRemoteState(), initialState);
+
+ // The selective sync blacklist should be not have been deleted.
+ bool ok = true;
+ QCOMPARE(fakeFolder.syncEngine().journal()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok),
+ selectiveSyncBlackList);
+ }
+
+ void testAllFilesDeletedDelete_data()
+ {
+ testAllFilesDeletedKeep_data();
+ }
+
+ /*
+ * This test is like the previous one but we simulate that the user presses "delete"
+ */
+ void testAllFilesDeletedDelete()
+ {
+ QFETCH(bool, deleteOnRemote);
+ FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
+
+ int aboutToRemoveAllFilesCalled = 0;
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveAllFiles,
+ [&](SyncFileItem::Direction dir, bool *cancel) {
+ QCOMPARE(aboutToRemoveAllFilesCalled, 0);
+ aboutToRemoveAllFilesCalled++;
+ QCOMPARE(dir, deleteOnRemote ? SyncFileItem::Down : SyncFileItem::Up);
+ *cancel = false;
+ });
+
+ auto &modifier = deleteOnRemote ? fakeFolder.remoteModifier() : fakeFolder.localModifier();
+ for (const auto &s : fakeFolder.currentRemoteState().children.keys())
+ modifier.remove(s);
+
+ QVERIFY(fakeFolder.syncOnce()); // Should succeed, and all files must then be deleted
+
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ QCOMPARE(fakeFolder.currentLocalState().children.count(), 0);
+
+ // Try another sync to be sure.
+
+ QVERIFY(fakeFolder.syncOnce()); // Should succeed (doing nothing)
+ QCOMPARE(aboutToRemoveAllFilesCalled, 1); // should not have been called.
+
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ QCOMPARE(fakeFolder.currentLocalState().children.count(), 0);
+ }
+};
+
+QTEST_GUILESS_MAIN(TestAllFilesDeleted)
+#include "testallfilesdeleted.moc"