| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 |
- /*
- * 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;
- bool itemDidComplete(const QSignalSpy &spy, const QString &path)
- {
- for(const QList<QVariant> &args : spy) {
- auto item = args[0].value<SyncFileItemPtr>();
- if (item->destination() == path)
- return true;
- }
- return false;
- }
- bool itemDidCompleteSuccessfully(const QSignalSpy &spy, const QString &path)
- {
- for(const QList<QVariant> &args : spy) {
- auto item = args[0].value<SyncFileItemPtr>();
- if (item->destination() == path)
- return item->_status == SyncFileItem::Success;
- }
- return false;
- }
- class TestSyncEngine : public QObject
- {
- Q_OBJECT
- private slots:
- void testFileDownload() {
- FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
- QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
- fakeFolder.remoteModifier().insert("A/a0");
- fakeFolder.syncOnce();
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "A/a0"));
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- }
- void testFileUpload() {
- FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
- QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
- fakeFolder.localModifier().insert("A/a0");
- fakeFolder.syncOnce();
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "A/a0"));
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- }
- void testDirDownload() {
- FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
- QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
- fakeFolder.remoteModifier().mkdir("Y");
- fakeFolder.remoteModifier().mkdir("Z");
- fakeFolder.remoteModifier().insert("Z/d0");
- fakeFolder.syncOnce();
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Y"));
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Z"));
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Z/d0"));
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- }
- void testDirUpload() {
- FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
- QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
- fakeFolder.localModifier().mkdir("Y");
- fakeFolder.localModifier().mkdir("Z");
- fakeFolder.localModifier().insert("Z/d0");
- fakeFolder.syncOnce();
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Y"));
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Z"));
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Z/d0"));
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- }
- void testLocalDelete() {
- FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
- QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
- fakeFolder.remoteModifier().remove("A/a1");
- fakeFolder.syncOnce();
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "A/a1"));
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- }
- void testRemoteDelete() {
- FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
- QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
- fakeFolder.localModifier().remove("A/a1");
- fakeFolder.syncOnce();
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "A/a1"));
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- }
- void testEmlLocalChecksum() {
- FakeFolder fakeFolder{FileInfo{}};
- fakeFolder.localModifier().insert("a1.eml", 64, 'A');
- fakeFolder.localModifier().insert("a2.eml", 64, 'A');
- fakeFolder.localModifier().insert("a3.eml", 64, 'A');
- fakeFolder.localModifier().insert("b3.txt", 64, 'A');
- // Upload and calculate the checksums
- // fakeFolder.syncOnce();
- fakeFolder.syncOnce();
- auto getDbChecksum = [&](QString path) {
- SyncJournalFileRecord record;
- fakeFolder.syncJournal().getFileRecord(path, &record);
- return record._checksumHeader;
- };
- // printf 'A%.0s' {1..64} | sha1sum -
- QByteArray referenceChecksum("SHA1:30b86e44e6001403827a62c58b08893e77cf121f");
- QCOMPARE(getDbChecksum("a1.eml"), referenceChecksum);
- QCOMPARE(getDbChecksum("a2.eml"), referenceChecksum);
- QCOMPARE(getDbChecksum("a3.eml"), referenceChecksum);
- QCOMPARE(getDbChecksum("b3.txt"), referenceChecksum);
- QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
- // Touch the file without changing the content, shouldn't upload
- fakeFolder.localModifier().setContents("a1.eml", 'A');
- // Change the content/size
- fakeFolder.localModifier().setContents("a2.eml", 'B');
- fakeFolder.localModifier().appendByte("a3.eml");
- fakeFolder.localModifier().appendByte("b3.txt");
- fakeFolder.syncOnce();
- QCOMPARE(getDbChecksum("a1.eml"), referenceChecksum);
- QCOMPARE(getDbChecksum("a2.eml"), QByteArray("SHA1:84951fc23a4dafd10020ac349da1f5530fa65949"));
- QCOMPARE(getDbChecksum("a3.eml"), QByteArray("SHA1:826b7e7a7af8a529ae1c7443c23bf185c0ad440c"));
- QCOMPARE(getDbChecksum("b3.eml"), getDbChecksum("a3.txt"));
- QVERIFY(!itemDidComplete(completeSpy, "a1.eml"));
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "a2.eml"));
- QVERIFY(itemDidCompleteSuccessfully(completeSpy, "a3.eml"));
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- }
- void testRemoteChangeInMovedFolder() {
- // issue #5192
- FakeFolder fakeFolder{FileInfo{ QString(), {
- FileInfo { QStringLiteral("folder"), {
- FileInfo{ QStringLiteral("folderA"), { { QStringLiteral("file.txt"), 400 } } },
- QStringLiteral("folderB")
- }
- }}}};
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- // Edit a file in a moved directory.
- fakeFolder.remoteModifier().setContents("folder/folderA/file.txt", 'a');
- fakeFolder.remoteModifier().rename("folder/folderA", "folder/folderB/folderA");
- fakeFolder.syncOnce();
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- auto oldState = fakeFolder.currentLocalState();
- QVERIFY(oldState.find("folder/folderB/folderA/file.txt"));
- QVERIFY(!oldState.find("folder/folderA/file.txt"));
- // This sync should not remove the file
- fakeFolder.syncOnce();
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- QCOMPARE(fakeFolder.currentLocalState(), oldState);
- }
- void testSelectiveSyncModevFolder() {
- // issue #5224
- FakeFolder fakeFolder{FileInfo{ QString(), {
- FileInfo { QStringLiteral("parentFolder"), {
- FileInfo{ QStringLiteral("subFolderA"), { { QStringLiteral("fileA.txt"), 400 } } },
- FileInfo{ QStringLiteral("subFolderB"), { { QStringLiteral("fileB.txt"), 400 } } }
- }
- }}}};
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- auto expectedServerState = fakeFolder.currentRemoteState();
- // Remove subFolderA with selectiveSync:
- fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
- {"parentFolder/subFolderA/"});
- fakeFolder.syncEngine().journal()->avoidReadFromDbOnNextSync(QByteArrayLiteral("parentFolder/subFolderA/"));
- fakeFolder.syncOnce();
- {
- // Nothing changed on the server
- QCOMPARE(fakeFolder.currentRemoteState(), expectedServerState);
- // The local state should not have subFolderA
- auto remoteState = fakeFolder.currentRemoteState();
- remoteState.remove("parentFolder/subFolderA");
- QCOMPARE(fakeFolder.currentLocalState(), remoteState);
- }
- // Rename parentFolder on the server
- fakeFolder.remoteModifier().rename("parentFolder", "parentFolderRenamed");
- expectedServerState = fakeFolder.currentRemoteState();
- fakeFolder.syncOnce();
- {
- QCOMPARE(fakeFolder.currentRemoteState(), expectedServerState);
- auto remoteState = fakeFolder.currentRemoteState();
- // The subFolderA should still be there on the server.
- QVERIFY(remoteState.find("parentFolderRenamed/subFolderA/fileA.txt"));
- // But not on the client because of the selective sync
- remoteState.remove("parentFolderRenamed/subFolderA");
- QCOMPARE(fakeFolder.currentLocalState(), remoteState);
- }
- // Rename it again, locally this time.
- fakeFolder.localModifier().rename("parentFolderRenamed", "parentThirdName");
- fakeFolder.syncOnce();
- {
- auto remoteState = fakeFolder.currentRemoteState();
- // The subFolderA should still be there on the server.
- QVERIFY(remoteState.find("parentThirdName/subFolderA/fileA.txt"));
- // But not on the client because of the selective sync
- remoteState.remove("parentThirdName/subFolderA");
- QCOMPARE(fakeFolder.currentLocalState(), remoteState);
- expectedServerState = fakeFolder.currentRemoteState();
- QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
- fakeFolder.syncOnce(); // This sync should do nothing
- QCOMPARE(completeSpy.count(), 0);
- QCOMPARE(fakeFolder.currentRemoteState(), expectedServerState);
- QCOMPARE(fakeFolder.currentLocalState(), remoteState);
- }
- }
- void testSelectiveSyncBug() {
- // issue owncloud/enterprise#1965: files from selective-sync ignored
- // folders are uploaded anyway is some circumstances.
- FakeFolder fakeFolder{FileInfo{ QString(), {
- FileInfo { QStringLiteral("parentFolder"), {
- FileInfo{ QStringLiteral("subFolderA"), {
- { QStringLiteral("fileA.txt"), 400 },
- { QStringLiteral("fileB.txt"), 400, 'o' },
- FileInfo { QStringLiteral("subsubFolder"), {
- { QStringLiteral("fileC.txt"), 400 },
- { QStringLiteral("fileD.txt"), 400, 'o' }
- }},
- FileInfo{ QStringLiteral("anotherFolder"), {
- FileInfo { QStringLiteral("emptyFolder"), { } },
- FileInfo { QStringLiteral("subsubFolder"), {
- { QStringLiteral("fileE.txt"), 400 },
- { QStringLiteral("fileF.txt"), 400, 'o' }
- }}
- }}
- }},
- FileInfo{ QStringLiteral("subFolderB"), {} }
- }}
- }}};
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- auto expectedServerState = fakeFolder.currentRemoteState();
- // Remove subFolderA with selectiveSync:
- fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
- {"parentFolder/subFolderA/"});
- fakeFolder.syncEngine().journal()->avoidReadFromDbOnNextSync(QByteArrayLiteral("parentFolder/subFolderA/"));
- // But touch local file before the next sync, such that the local folder
- // can't be removed
- fakeFolder.localModifier().setContents("parentFolder/subFolderA/fileB.txt", 'n');
- fakeFolder.localModifier().setContents("parentFolder/subFolderA/subsubFolder/fileD.txt", 'n');
- fakeFolder.localModifier().setContents("parentFolder/subFolderA/anotherFolder/subsubFolder/fileF.txt", 'n');
- // Several follow-up syncs don't change the state at all,
- // in particular the remote state doesn't change and fileB.txt
- // isn't uploaded.
- for (int i = 0; i < 3; ++i) {
- fakeFolder.syncOnce();
- {
- // Nothing changed on the server
- QCOMPARE(fakeFolder.currentRemoteState(), expectedServerState);
- // The local state should still have subFolderA
- auto local = fakeFolder.currentLocalState();
- QVERIFY(local.find("parentFolder/subFolderA"));
- QVERIFY(!local.find("parentFolder/subFolderA/fileA.txt"));
- QVERIFY(local.find("parentFolder/subFolderA/fileB.txt"));
- QVERIFY(!local.find("parentFolder/subFolderA/subsubFolder/fileC.txt"));
- QVERIFY(local.find("parentFolder/subFolderA/subsubFolder/fileD.txt"));
- QVERIFY(!local.find("parentFolder/subFolderA/anotherFolder/subsubFolder/fileE.txt"));
- QVERIFY(local.find("parentFolder/subFolderA/anotherFolder/subsubFolder/fileF.txt"));
- QVERIFY(!local.find("parentFolder/subFolderA/anotherFolder/emptyFolder"));
- QVERIFY(local.find("parentFolder/subFolderB"));
- }
- }
- }
- void abortAfterFailedMkdir() {
- FakeFolder fakeFolder{FileInfo{}};
- QSignalSpy finishedSpy(&fakeFolder.syncEngine(), SIGNAL(finished(bool)));
- fakeFolder.serverErrorPaths().append("NewFolder");
- fakeFolder.localModifier().mkdir("NewFolder");
- // This should be aborted and would otherwise fail in FileInfo::create.
- fakeFolder.localModifier().insert("NewFolder/NewFile");
- fakeFolder.syncOnce();
- QCOMPARE(finishedSpy.size(), 1);
- QCOMPARE(finishedSpy.first().first().toBool(), false);
- }
- void testDirDownloadWithError() {
- FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
- QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
- fakeFolder.remoteModifier().mkdir("Y");
- fakeFolder.remoteModifier().mkdir("Y/Z");
- fakeFolder.remoteModifier().insert("Y/Z/d0");
- fakeFolder.remoteModifier().insert("Y/Z/d1");
- fakeFolder.remoteModifier().insert("Y/Z/d2");
- fakeFolder.remoteModifier().insert("Y/Z/d3");
- fakeFolder.remoteModifier().insert("Y/Z/d4");
- fakeFolder.remoteModifier().insert("Y/Z/d5");
- fakeFolder.remoteModifier().insert("Y/Z/d6");
- fakeFolder.remoteModifier().insert("Y/Z/d7");
- fakeFolder.remoteModifier().insert("Y/Z/d8");
- fakeFolder.remoteModifier().insert("Y/Z/d9");
- fakeFolder.serverErrorPaths().append("Y/Z/d2", 503); // 503 is a fatal error
- fakeFolder.serverErrorPaths().append("Y/Z/d3", 503); // 503 is a fatal error
- QVERIFY(!fakeFolder.syncOnce());
- QCoreApplication::processEvents(); // should not crash
- QSet<QString> seen;
- for(const QList<QVariant> &args : completeSpy) {
- auto item = args[0].value<SyncFileItemPtr>();
- qDebug() << item->_file << item->isDirectory() << item->_status;
- QVERIFY(!seen.contains(item->_file)); // signal only sent once per item
- seen.insert(item->_file);
- if (item->_file == "Y/Z/d2") {
- QVERIFY(item->_status == SyncFileItem::FatalError);
- } else if(item->_file == "Y/Z/d3") {
- QVERIFY(item->_status != SyncFileItem::Success);
- }
- QVERIFY(item->_file != "Y/Z/d9"); // we should have aborted the sync before d9 starts
- }
- }
- void testFakeConflict()
- {
- FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
- int nGET = 0;
- fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &) {
- if (op == QNetworkAccessManager::GetOperation)
- ++nGET;
- return nullptr;
- });
- // For directly editing the remote checksum
- FileInfo &remoteInfo = dynamic_cast<FileInfo &>(fakeFolder.remoteModifier());
- // Base mtime with no ms content (filesystem is seconds only)
- auto mtime = QDateTime::currentDateTimeUtc().addDays(-4);
- mtime.setMSecsSinceEpoch(mtime.toMSecsSinceEpoch() / 1000 * 1000);
- // Conflict: Same content, mtime, but no server checksum
- // -> ignored in reconcile
- fakeFolder.localModifier().setContents("A/a1", 'C');
- fakeFolder.localModifier().setModTime("A/a1", mtime);
- fakeFolder.remoteModifier().setContents("A/a1", 'C');
- fakeFolder.remoteModifier().setModTime("A/a1", mtime);
- QVERIFY(fakeFolder.syncOnce());
- QCOMPARE(nGET, 0);
- // Conflict: Same content, mtime, but weak server checksum
- // -> ignored in reconcile
- mtime = mtime.addDays(1);
- fakeFolder.localModifier().setContents("A/a1", 'D');
- fakeFolder.localModifier().setModTime("A/a1", mtime);
- fakeFolder.remoteModifier().setContents("A/a1", 'D');
- fakeFolder.remoteModifier().setModTime("A/a1", mtime);
- remoteInfo.find("A/a1")->checksums = "Adler32:bad";
- QVERIFY(fakeFolder.syncOnce());
- QCOMPARE(nGET, 0);
- // Conflict: Same content, mtime, but server checksum differs
- // -> downloaded
- mtime = mtime.addDays(1);
- fakeFolder.localModifier().setContents("A/a1", 'W');
- fakeFolder.localModifier().setModTime("A/a1", mtime);
- fakeFolder.remoteModifier().setContents("A/a1", 'W');
- fakeFolder.remoteModifier().setModTime("A/a1", mtime);
- remoteInfo.find("A/a1")->checksums = "SHA1:bad";
- QVERIFY(fakeFolder.syncOnce());
- QCOMPARE(nGET, 1);
- // Conflict: Same content, mtime, matching checksums
- // -> PropagateDownload, but it skips the download
- mtime = mtime.addDays(1);
- fakeFolder.localModifier().setContents("A/a1", 'C');
- fakeFolder.localModifier().setModTime("A/a1", mtime);
- fakeFolder.remoteModifier().setContents("A/a1", 'C');
- fakeFolder.remoteModifier().setModTime("A/a1", mtime);
- remoteInfo.find("A/a1")->checksums = "SHA1:56900fb1d337cf7237ff766276b9c1e8ce507427";
- QVERIFY(fakeFolder.syncOnce());
- QCOMPARE(nGET, 1);
- // Extra sync reads from db, no difference
- QVERIFY(fakeFolder.syncOnce());
- QCOMPARE(nGET, 1);
- }
- /**
- * Checks whether SyncFileItems have the expected properties before start
- * of propagation.
- */
- void testSyncFileItemProperties()
- {
- auto initialMtime = QDateTime::currentDateTimeUtc().addDays(-7);
- auto changedMtime = QDateTime::currentDateTimeUtc().addDays(-4);
- auto changedMtime2 = QDateTime::currentDateTimeUtc().addDays(-3);
- // Base mtime with no ms content (filesystem is seconds only)
- initialMtime.setMSecsSinceEpoch(initialMtime.toMSecsSinceEpoch() / 1000 * 1000);
- changedMtime.setMSecsSinceEpoch(changedMtime.toMSecsSinceEpoch() / 1000 * 1000);
- changedMtime2.setMSecsSinceEpoch(changedMtime2.toMSecsSinceEpoch() / 1000 * 1000);
- // Ensure the initial mtimes are as expected
- auto initialFileInfo = FileInfo::A12_B12_C12_S12();
- initialFileInfo.setModTime("A/a1", initialMtime);
- initialFileInfo.setModTime("B/b1", initialMtime);
- initialFileInfo.setModTime("C/c1", initialMtime);
- FakeFolder fakeFolder{ initialFileInfo };
- // upload a
- fakeFolder.localModifier().appendByte("A/a1");
- fakeFolder.localModifier().setModTime("A/a1", changedMtime);
- // download b
- fakeFolder.remoteModifier().appendByte("B/b1");
- fakeFolder.remoteModifier().setModTime("B/b1", changedMtime);
- // conflict c
- fakeFolder.localModifier().appendByte("C/c1");
- fakeFolder.localModifier().appendByte("C/c1");
- fakeFolder.localModifier().setModTime("C/c1", changedMtime);
- fakeFolder.remoteModifier().appendByte("C/c1");
- fakeFolder.remoteModifier().setModTime("C/c1", changedMtime2);
- connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToPropagate, [&](SyncFileItemVector &items) {
- SyncFileItemPtr a1, b1, c1;
- for (auto &item : items) {
- if (item->_file == "A/a1")
- a1 = item;
- if (item->_file == "B/b1")
- b1 = item;
- if (item->_file == "C/c1")
- c1 = item;
- }
- // a1: should have local size and modtime
- QVERIFY(a1);
- QCOMPARE(a1->_instruction, CSYNC_INSTRUCTION_SYNC);
- QCOMPARE(a1->_direction, SyncFileItem::Up);
- QCOMPARE(a1->_size, quint64(5));
- QCOMPARE(Utility::qDateTimeFromTime_t(a1->_modtime), changedMtime);
- QCOMPARE(a1->_previousSize, quint64(4));
- QCOMPARE(Utility::qDateTimeFromTime_t(a1->_previousModtime), initialMtime);
- // b2: should have remote size and modtime
- QVERIFY(b1);
- QCOMPARE(b1->_instruction, CSYNC_INSTRUCTION_SYNC);
- QCOMPARE(b1->_direction, SyncFileItem::Down);
- QCOMPARE(b1->_size, quint64(17));
- QCOMPARE(Utility::qDateTimeFromTime_t(b1->_modtime), changedMtime);
- QCOMPARE(b1->_previousSize, quint64(16));
- QCOMPARE(Utility::qDateTimeFromTime_t(b1->_previousModtime), initialMtime);
- // c1: conflicts are downloads, so remote size and modtime
- QVERIFY(c1);
- QCOMPARE(c1->_instruction, CSYNC_INSTRUCTION_CONFLICT);
- QCOMPARE(c1->_direction, SyncFileItem::None);
- QCOMPARE(c1->_size, quint64(25));
- QCOMPARE(Utility::qDateTimeFromTime_t(c1->_modtime), changedMtime2);
- QCOMPARE(c1->_previousSize, quint64(26));
- QCOMPARE(Utility::qDateTimeFromTime_t(c1->_previousModtime), changedMtime);
- });
- QVERIFY(fakeFolder.syncOnce());
- }
- /**
- * Checks whether subsequent large uploads are skipped after a 507 error
- */
- void testInsufficientRemoteStorage()
- {
- FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
- // Disable parallel uploads
- SyncOptions syncOptions;
- syncOptions._parallelNetworkJobs = false;
- fakeFolder.syncEngine().setSyncOptions(syncOptions);
- // Produce an error based on upload size
- int remoteQuota = 1000;
- int n507 = 0, nPUT = 0;
- auto parent = new QObject;
- fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &request) -> QNetworkReply * {
- if (op == QNetworkAccessManager::PutOperation) {
- nPUT++;
- if (request.rawHeader("OC-Total-Length").toInt() > remoteQuota) {
- n507++;
- return new FakeErrorReply(op, request, parent, 507);
- }
- }
- return nullptr;
- });
- fakeFolder.localModifier().insert("A/big", 800);
- QVERIFY(fakeFolder.syncOnce());
- QCOMPARE(nPUT, 1);
- QCOMPARE(n507, 0);
- nPUT = 0;
- fakeFolder.localModifier().insert("A/big1", 500); // ok
- fakeFolder.localModifier().insert("A/big2", 1200); // 507 (quota guess now 1199)
- fakeFolder.localModifier().insert("A/big3", 1200); // skipped
- fakeFolder.localModifier().insert("A/big4", 1500); // skipped
- fakeFolder.localModifier().insert("A/big5", 1100); // 507 (quota guess now 1099)
- fakeFolder.localModifier().insert("A/big6", 900); // ok (quota guess now 199)
- fakeFolder.localModifier().insert("A/big7", 200); // skipped
- fakeFolder.localModifier().insert("A/big8", 199); // ok (quota guess now 0)
- fakeFolder.localModifier().insert("B/big8", 1150); // 507
- QVERIFY(!fakeFolder.syncOnce());
- QCOMPARE(nPUT, 6);
- QCOMPARE(n507, 3);
- }
- };
- QTEST_GUILESS_MAIN(TestSyncEngine)
- #include "testsyncengine.moc"
|