From 16ba0cf47ea95a38a25a8d3419ad43c6eba2d821 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Wed, 28 Mar 2018 11:04:58 +0200 Subject: Blacklist: Add unittest #6411 --- test/CMakeLists.txt | 1 + test/testblacklist.cpp | 187 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 test/testblacklist.cpp (limited to 'test') diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5f36690a7..bb184412b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -48,6 +48,7 @@ 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(Blacklist "syncenginetestutils.h") owncloud_add_test(FolderWatcher "${FolderWatcher_SRC}") if( UNIX AND NOT APPLE ) diff --git a/test/testblacklist.cpp b/test/testblacklist.cpp new file mode 100644 index 000000000..f571affa4 --- /dev/null +++ b/test/testblacklist.cpp @@ -0,0 +1,187 @@ +/* + * 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 +#include "syncenginetestutils.h" +#include + +using namespace OCC; + +SyncFileItemPtr findItem(const QSignalSpy &spy, const QString &path) +{ + for (const QList &args : spy) { + auto item = args[0].value(); + if (item->destination() == path) + return item; + } + return SyncFileItemPtr(new SyncFileItem); +} + +SyncJournalFileRecord journalRecord(FakeFolder &folder, const QByteArray &path) +{ + SyncJournalFileRecord rec; + folder.syncJournal().getFileRecord(path, &rec); + return rec; +} + +class TestBlacklist : public QObject +{ + Q_OBJECT + +private slots: + void testBlacklistBasic_data() + { + QTest::addColumn("remote"); + QTest::newRow("remote") << true; + QTest::newRow("local") << false; + } + + void testBlacklistBasic() + { + QFETCH(bool, remote); + + FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &))); + + auto &modifier = remote ? fakeFolder.remoteModifier() : fakeFolder.localModifier(); + + int counter = 0; + fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &, QIODevice *) -> QNetworkReply * { + if (!remote && op == QNetworkAccessManager::PutOperation) + ++counter; + if (remote && op == QNetworkAccessManager::GetOperation) + ++counter; + return nullptr; + }); + + auto cleanup = [&]() { + completeSpy.clear(); + }; + + auto initialEtag = journalRecord(fakeFolder, "A")._etag; + QVERIFY(!initialEtag.isEmpty()); + + // The first sync and the download will fail - the item will be blacklisted + modifier.insert("A/new"); + fakeFolder.serverErrorPaths().append("A/new", 500); // will be blacklisted + QVERIFY(!fakeFolder.syncOnce()); + { + auto it = findItem(completeSpy, "A/new"); + QVERIFY(it); + QCOMPARE(it->_status, SyncFileItem::NormalError); // initial error visible + QCOMPARE(it->_instruction, CSYNC_INSTRUCTION_NEW); + + auto entry = fakeFolder.syncJournal().errorBlacklistEntry("A/new"); + QVERIFY(entry.isValid()); + QCOMPARE(entry._errorCategory, SyncJournalErrorBlacklistRecord::Normal); + QCOMPARE(entry._retryCount, 1); + QCOMPARE(counter, 1); + QVERIFY(entry._ignoreDuration > 0); + + if (remote) + QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag); + } + cleanup(); + + // Ignored during the second run - but soft errors are also errors + QVERIFY(!fakeFolder.syncOnce()); + { + auto it = findItem(completeSpy, "A/new"); + QVERIFY(it); + QCOMPARE(it->_status, SyncFileItem::BlacklistedError); + QCOMPARE(it->_instruction, CSYNC_INSTRUCTION_IGNORE); // no retry happened! + + auto entry = fakeFolder.syncJournal().errorBlacklistEntry("A/new"); + QVERIFY(entry.isValid()); + QCOMPARE(entry._errorCategory, SyncJournalErrorBlacklistRecord::Normal); + QCOMPARE(entry._retryCount, 1); + QCOMPARE(counter, 1); + QVERIFY(entry._ignoreDuration > 0); + + if (remote) + QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag); + } + cleanup(); + + // Let's expire the blacklist entry to verify it gets retried + { + auto entry = fakeFolder.syncJournal().errorBlacklistEntry("A/new"); + entry._ignoreDuration = 1; + entry._lastTryTime -= 1; + fakeFolder.syncJournal().setErrorBlacklistEntry(entry); + } + QVERIFY(!fakeFolder.syncOnce()); + { + auto it = findItem(completeSpy, "A/new"); + QVERIFY(it); + QCOMPARE(it->_status, SyncFileItem::BlacklistedError); // blacklisted as it's just a retry + QCOMPARE(it->_instruction, CSYNC_INSTRUCTION_NEW); // retry! + + auto entry = fakeFolder.syncJournal().errorBlacklistEntry("A/new"); + QVERIFY(entry.isValid()); + QCOMPARE(entry._errorCategory, SyncJournalErrorBlacklistRecord::Normal); + QCOMPARE(entry._retryCount, 2); + QCOMPARE(counter, 2); + QVERIFY(entry._ignoreDuration > 0); + + if (remote) + QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag); + } + cleanup(); + + // When the file changes a retry happens immediately + modifier.appendByte("A/new"); + QVERIFY(!fakeFolder.syncOnce()); + { + auto it = findItem(completeSpy, "A/new"); + QVERIFY(it); + QCOMPARE(it->_status, SyncFileItem::BlacklistedError); + QCOMPARE(it->_instruction, CSYNC_INSTRUCTION_NEW); // retry! + + auto entry = fakeFolder.syncJournal().errorBlacklistEntry("A/new"); + QVERIFY(entry.isValid()); + QCOMPARE(entry._errorCategory, SyncJournalErrorBlacklistRecord::Normal); + QCOMPARE(entry._retryCount, 3); + QCOMPARE(counter, 3); + QVERIFY(entry._ignoreDuration > 0); + + if (remote) + QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag); + } + cleanup(); + + // When the error goes away and the item is retried, the sync succeeds + fakeFolder.serverErrorPaths().clear(); + { + auto entry = fakeFolder.syncJournal().errorBlacklistEntry("A/new"); + entry._ignoreDuration = 1; + entry._lastTryTime -= 1; + fakeFolder.syncJournal().setErrorBlacklistEntry(entry); + } + QVERIFY(fakeFolder.syncOnce()); + { + auto it = findItem(completeSpy, "A/new"); + QVERIFY(it); + QCOMPARE(it->_status, SyncFileItem::Success); + QCOMPARE(it->_instruction, CSYNC_INSTRUCTION_NEW); + + auto entry = fakeFolder.syncJournal().errorBlacklistEntry("A/new"); + QVERIFY(!entry.isValid()); + QCOMPARE(counter, 4); + + if (remote) + QCOMPARE(journalRecord(fakeFolder, "A")._etag, fakeFolder.currentRemoteState().find("A")->etag.toUtf8()); + } + cleanup(); + + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } +}; + +QTEST_GUILESS_MAIN(TestBlacklist) +#include "testblacklist.moc" -- cgit v1.2.3