testblacklist.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * This software is in the public domain, furnished "as is", without technical
  3. * support, and with no warranty, express or implied, as to its usefulness for
  4. * any purpose.
  5. *
  6. */
  7. #include <QtTest>
  8. #include "syncenginetestutils.h"
  9. #include <syncengine.h>
  10. using namespace OCC;
  11. SyncJournalFileRecord journalRecord(FakeFolder &folder, const QByteArray &path)
  12. {
  13. SyncJournalFileRecord rec;
  14. folder.syncJournal().getFileRecord(path, &rec);
  15. return rec;
  16. }
  17. class TestBlacklist : public QObject
  18. {
  19. Q_OBJECT
  20. private slots:
  21. void testBlacklistBasic_data()
  22. {
  23. QTest::addColumn<bool>("remote");
  24. QTest::newRow("remote") << true;
  25. QTest::newRow("local") << false;
  26. }
  27. void testBlacklistBasic()
  28. {
  29. QFETCH(bool, remote);
  30. FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
  31. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  32. ItemCompletedSpy completeSpy(fakeFolder);
  33. auto &modifier = remote ? fakeFolder.remoteModifier() : fakeFolder.localModifier();
  34. int counter = 0;
  35. const QByteArray testFileName = QByteArrayLiteral("A/new");
  36. QByteArray reqId;
  37. fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *) -> QNetworkReply * {
  38. if (req.url().path().endsWith(testFileName)) {
  39. reqId = req.rawHeader("X-Request-ID");
  40. }
  41. if (!remote && op == QNetworkAccessManager::PutOperation)
  42. ++counter;
  43. if (remote && op == QNetworkAccessManager::GetOperation)
  44. ++counter;
  45. return nullptr;
  46. });
  47. auto cleanup = [&]() {
  48. completeSpy.clear();
  49. };
  50. auto initialEtag = journalRecord(fakeFolder, "A")._etag;
  51. QVERIFY(!initialEtag.isEmpty());
  52. // The first sync and the download will fail - the item will be blacklisted
  53. modifier.insert(testFileName);
  54. fakeFolder.serverErrorPaths().append(testFileName, 500); // will be blacklisted
  55. QVERIFY(!fakeFolder.syncOnce());
  56. {
  57. auto it = completeSpy.findItem(testFileName);
  58. QVERIFY(it);
  59. QCOMPARE(it->_status, SyncFileItem::NormalError); // initial error visible
  60. QCOMPARE(it->_instruction, CSYNC_INSTRUCTION_NEW);
  61. auto entry = fakeFolder.syncJournal().errorBlacklistEntry(testFileName);
  62. QVERIFY(entry.isValid());
  63. QCOMPARE(entry._errorCategory, SyncJournalErrorBlacklistRecord::Normal);
  64. QCOMPARE(entry._retryCount, 1);
  65. QCOMPARE(counter, 1);
  66. QVERIFY(entry._ignoreDuration > 0);
  67. QCOMPARE(entry._requestId, reqId);
  68. if (remote)
  69. QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag);
  70. }
  71. cleanup();
  72. // Ignored during the second run - but soft errors are also errors
  73. QVERIFY(!fakeFolder.syncOnce());
  74. {
  75. auto it = completeSpy.findItem(testFileName);
  76. QVERIFY(it);
  77. QCOMPARE(it->_status, SyncFileItem::BlacklistedError);
  78. QCOMPARE(it->_instruction, CSYNC_INSTRUCTION_IGNORE); // no retry happened!
  79. auto entry = fakeFolder.syncJournal().errorBlacklistEntry(testFileName);
  80. QVERIFY(entry.isValid());
  81. QCOMPARE(entry._errorCategory, SyncJournalErrorBlacklistRecord::Normal);
  82. QCOMPARE(entry._retryCount, 1);
  83. QCOMPARE(counter, 1);
  84. QVERIFY(entry._ignoreDuration > 0);
  85. QCOMPARE(entry._requestId, reqId);
  86. if (remote)
  87. QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag);
  88. }
  89. cleanup();
  90. // Let's expire the blacklist entry to verify it gets retried
  91. {
  92. auto entry = fakeFolder.syncJournal().errorBlacklistEntry(testFileName);
  93. entry._ignoreDuration = 1;
  94. entry._lastTryTime -= 1;
  95. fakeFolder.syncJournal().setErrorBlacklistEntry(entry);
  96. }
  97. QVERIFY(!fakeFolder.syncOnce());
  98. {
  99. auto it = completeSpy.findItem(testFileName);
  100. QVERIFY(it);
  101. QCOMPARE(it->_status, SyncFileItem::BlacklistedError); // blacklisted as it's just a retry
  102. QCOMPARE(it->_instruction, CSYNC_INSTRUCTION_NEW); // retry!
  103. auto entry = fakeFolder.syncJournal().errorBlacklistEntry(testFileName);
  104. QVERIFY(entry.isValid());
  105. QCOMPARE(entry._errorCategory, SyncJournalErrorBlacklistRecord::Normal);
  106. QCOMPARE(entry._retryCount, 2);
  107. QCOMPARE(counter, 2);
  108. QVERIFY(entry._ignoreDuration > 0);
  109. QCOMPARE(entry._requestId, reqId);
  110. if (remote)
  111. QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag);
  112. }
  113. cleanup();
  114. // When the file changes a retry happens immediately
  115. modifier.appendByte(testFileName);
  116. QVERIFY(!fakeFolder.syncOnce());
  117. {
  118. auto it = completeSpy.findItem(testFileName);
  119. QVERIFY(it);
  120. QCOMPARE(it->_status, SyncFileItem::BlacklistedError);
  121. QCOMPARE(it->_instruction, CSYNC_INSTRUCTION_NEW); // retry!
  122. auto entry = fakeFolder.syncJournal().errorBlacklistEntry(testFileName);
  123. QVERIFY(entry.isValid());
  124. QCOMPARE(entry._errorCategory, SyncJournalErrorBlacklistRecord::Normal);
  125. QCOMPARE(entry._retryCount, 3);
  126. QCOMPARE(counter, 3);
  127. QVERIFY(entry._ignoreDuration > 0);
  128. QCOMPARE(entry._requestId, reqId);
  129. if (remote)
  130. QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag);
  131. }
  132. cleanup();
  133. // When the error goes away and the item is retried, the sync succeeds
  134. fakeFolder.serverErrorPaths().clear();
  135. {
  136. auto entry = fakeFolder.syncJournal().errorBlacklistEntry(testFileName);
  137. entry._ignoreDuration = 1;
  138. entry._lastTryTime -= 1;
  139. fakeFolder.syncJournal().setErrorBlacklistEntry(entry);
  140. }
  141. QVERIFY(fakeFolder.syncOnce());
  142. {
  143. auto it = completeSpy.findItem(testFileName);
  144. QVERIFY(it);
  145. QCOMPARE(it->_status, SyncFileItem::Success);
  146. QCOMPARE(it->_instruction, CSYNC_INSTRUCTION_NEW);
  147. auto entry = fakeFolder.syncJournal().errorBlacklistEntry(testFileName);
  148. QVERIFY(!entry.isValid());
  149. QCOMPARE(counter, 4);
  150. if (remote)
  151. QCOMPARE(journalRecord(fakeFolder, "A")._etag, fakeFolder.currentRemoteState().find("A")->etag);
  152. }
  153. cleanup();
  154. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  155. }
  156. };
  157. QTEST_GUILESS_MAIN(TestBlacklist)
  158. #include "testblacklist.moc"