bool SyncJournalDb::checkConnect()
{
+ if (autotestFailCounter >= 0) {
+ if (!autotestFailCounter--) {
+ qCInfo(lcDb) << "Error Simulated";
+ return false;
+ }
+ }
+
if (_db.isOpen()) {
// Unfortunately the sqlite isOpen check can return true even when the underlying storage
// has become unavailable - and then some operations may cause crashes. See #6049
bool re = true;
// check if the file_id column is there and create it if not
- if (!checkConnect()) {
+ if (columns.isEmpty()) {
return false;
}
commitInternal("update database structure: add isE2eEncrypted col");
}
- if (!tableColumns("uploadinfo").contains("contentChecksum")) {
+ auto uploadInfoColumns = tableColumns("uploadinfo");
+ if (uploadInfoColumns.isEmpty())
+ return false;
+ if (!uploadInfoColumns.contains("contentChecksum")) {
SqlQuery query(_db);
query.prepare("ALTER TABLE uploadinfo ADD COLUMN contentChecksum TEXT;");
if (!query.exec()) {
commitInternal("update database structure: add contentChecksum col for uploadinfo");
}
- if (!tableColumns("conflicts").contains("basePath")) {
+ auto conflictsColumns = tableColumns("conflicts");
+ if (conflictsColumns.isEmpty())
+ return false;
+ if (!conflictsColumns.contains("basePath")) {
SqlQuery query(_db);
query.prepare("ALTER TABLE conflicts ADD COLUMN basePath TEXT;");
if (!query.exec()) {
auto columns = tableColumns("blacklist");
bool re = true;
- // check if the file_id column is there and create it if not
- if (!checkConnect()) {
+ if (columns.isEmpty()) {
return false;
}
#include "filesystem.h"
#include "syncengine.h"
#include "common/syncjournaldb.h"
+#include "csync_exclude.h"
#include <QDir>
#include <QNetworkReply>
_journalDb = std::make_unique<OCC::SyncJournalDb>(localPath() + "._sync_test.db");
_syncEngine = std::make_unique<OCC::SyncEngine>(_account, localPath(), "", _journalDb.get());
+ // Ignore temporary files from the download. (This is in the default exclude list, but we don't load it)
+ _syncEngine->excludedFiles().addManualExclude("]*.~*");
// 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
--- /dev/null
+/*
+ * 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;
+
+
+class TestDatabaseError : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testDatabaseError() {
+ /* This test will make many iteration, at each iteration, the iᵗʰ database access will fail.
+ * The test ensure that if there is a failure, the next sync recovers. And if there was
+ * no error, then everything was sync'ed properly.
+ */
+
+ FileInfo finalState;
+ for (int count = 0; true; ++count) {
+ qInfo() << "Starting Iteration" << count;
+
+ FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
+
+ // Do a couple of changes
+ fakeFolder.remoteModifier().insert("A/a0");
+ fakeFolder.remoteModifier().appendByte("A/a1");
+ fakeFolder.remoteModifier().remove("A/a2");
+ fakeFolder.remoteModifier().rename("S/s1", "S/s1_renamed");
+ fakeFolder.remoteModifier().mkdir("D");
+ fakeFolder.remoteModifier().mkdir("D/subdir");
+ fakeFolder.remoteModifier().insert("D/subdir/file");
+ fakeFolder.localModifier().insert("B/b0");
+ fakeFolder.localModifier().appendByte("B/b1");
+ fakeFolder.remoteModifier().remove("B/b2");
+ fakeFolder.localModifier().mkdir("NewDir");
+ fakeFolder.localModifier().rename("C", "NewDir/C");
+
+ // Set the counter
+ fakeFolder.syncJournal().autotestFailCounter = count;
+
+ // run the sync
+ bool result = fakeFolder.syncOnce();
+
+ qInfo() << "Result of iteration" << count << "was" << result;
+
+ if (fakeFolder.syncJournal().autotestFailCounter >= 0) {
+ // No error was thrown, we are finished
+ QVERIFY(result);
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ QCOMPARE(fakeFolder.currentRemoteState(), finalState);
+ return;
+ }
+
+ if (!result) {
+ fakeFolder.syncJournal().autotestFailCounter = -1;
+ // Try again
+ QVERIFY(fakeFolder.syncOnce());
+ }
+
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ if (count == 0) {
+ finalState = fakeFolder.currentRemoteState();
+ } else {
+ // the final state should be the same for every iteration
+ QCOMPARE(fakeFolder.currentRemoteState(), finalState);
+ }
+ }
+ }
+};
+
+QTEST_GUILESS_MAIN(TestDatabaseError)
+#include "testdatabaseerror.moc"