if (_localQueryDone)
process();
} else {
- if (results.error().code == 403) {
- // 403 Forbidden can be sent by the server if the file firewall is active.
- // A file or directory should be ignored and sync must continue. See #3490
- qCWarning(lcDisco, "Directory access Forbidden (File Firewall?)");
+ auto fatalError = [&] {
+ emit _discoveryData->fatalError(tr("Server replied with an error while reading directory '%1' : %2")
+ .arg(_currentFolder._server, results.error().message));
+ };
+ auto ignoreOrFatal = [&] {
if (_dirItem) {
_dirItem->_instruction = CSYNC_INSTRUCTION_IGNORE;
_dirItem->_errorString = results.error().message;
emit finished();
- return;
+ } else {
+ // Fatal for the root job since it has no SyncFileItem
+ fatalError();
}
+ };
+
+ if (results.error().code == 403) {
+ // 403 Forbidden can be sent by the server if the file firewall is active.
+ // A file or directory should be ignored and sync must continue. See #3490
+ qCWarning(lcDisco, "Directory access Forbidden (File Firewall?)");
+ ignoreOrFatal();
} else if (results.error().code == 503) {
// The server usually replies with the custom "503 Storage not available"
// if some path is temporarily unavailable. But in some cases a standard 503
// is returned too. Thus we can't distinguish the two and will treat any
// 503 as request to ignore the folder. See #3113 #2884.
qCWarning(lcDisco(), "Storage was not available!");
- if (_dirItem) {
- _dirItem->_instruction = CSYNC_INSTRUCTION_IGNORE;
- _dirItem->_errorString = results.error().message;
- emit finished();
- return;
- }
+ ignoreOrFatal();
+ } else {
+ qCWarning(lcDisco) << "Server error in directory" << _currentFolder._server << results.error().message;
+ fatalError();
}
- emit _discoveryData->fatalError(tr("Server replied with an error while reading directory '%1' : %2")
- .arg(_currentFolder._server, results.error().message));
}
});
connect(serverJob, &DiscoverySingleDirectoryJob::firstDirectoryPermissions, this,
QTest::addColumn<int>("errorKind");
QTest::addColumn<QString>("expectedErrorString");
- QString httpErrorMessage = "Server replied with an error while reading directory 'B' : Internal Server Fake Error";
+ QString itemErrorMessage = "Internal Server Fake Error";
- QTest::newRow("404") << 404 << httpErrorMessage;
- QTest::newRow("500") << 500 << httpErrorMessage;
- QTest::newRow("503") << 503 << httpErrorMessage;
+ QTest::newRow("403") << 403 << itemErrorMessage;
+ QTest::newRow("404") << 404 << itemErrorMessage;
+ QTest::newRow("500") << 500 << itemErrorMessage;
+ QTest::newRow("503") << 503 << itemErrorMessage;
// 200 should be an error since propfind should return 207
- QTest::newRow("200") << 200 << httpErrorMessage;
- QTest::newRow("InvalidXML") << +InvalidXML << "error while reading directory 'B' : Unknown error";
- QTest::newRow("Timeout") << +Timeout << "error while reading directory 'B' : Operation canceled";
+ QTest::newRow("200") << 200 << itemErrorMessage;
+ QTest::newRow("InvalidXML") << +InvalidXML << "Unknown error";
+ QTest::newRow("Timeout") << +Timeout << "Operation canceled";
}
{
QFETCH(int, errorKind);
QFETCH(QString, expectedErrorString);
- bool syncSucceeds = errorKind == 503; // 503 just ignore the temporarily unavailable directory
+ // 403/503 just ignore the temporarily unavailable directory
+ bool syncSucceeds = errorKind == 503 || errorKind == 403;
FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
auto oldLocalState = fakeFolder.currentLocalState();
auto oldRemoteState = fakeFolder.currentRemoteState();
+ QString errorFolder = "webdav/B";
+ QString fatalErrorPrefix = "Server replied with an error while reading directory 'B' : ";
fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *)
-> QNetworkReply *{
- if (req.attribute(QNetworkRequest::CustomVerbAttribute) == "PROPFIND" && req.url().path().endsWith("/B")) {
+ if (req.attribute(QNetworkRequest::CustomVerbAttribute) == "PROPFIND" && req.url().path().endsWith(errorFolder)) {
if (errorKind == InvalidXML) {
return new FakeBrokenXmlPropfindReply(fakeFolder.remoteModifier(), op, req, this);
} else if (errorKind == Timeout) {
// So the test that test timeout finishes fast
QScopedValueRollback<int> setHttpTimeout(AbstractNetworkJob::httpTimeout, errorKind == Timeout ? 1 : 10000);
+ QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
QSignalSpy errorSpy(&fakeFolder.syncEngine(), &SyncEngine::syncError);
QCOMPARE(fakeFolder.syncOnce(), syncSucceeds);
- qDebug() << "errorSpy=" << errorSpy;
// The folder B should not have been sync'ed (and in particular not removed)
QCOMPARE(oldLocalState.children["B"], fakeFolder.currentLocalState().children["B"]);
QCOMPARE(oldRemoteState.children["B"], fakeFolder.currentRemoteState().children["B"]);
if (!syncSucceeds) {
- // Check we got the right error
- QCOMPARE(errorSpy.count(), 1);
- QVERIFY(errorSpy[0][0].toString().contains(expectedErrorString));
+ QCOMPARE(errorSpy.size(), 1);
+ QCOMPARE(errorSpy[0][0].toString(), QString(fatalErrorPrefix + expectedErrorString));
} else {
+ QCOMPARE(findItem(completeSpy, "B")->_instruction, CSYNC_INSTRUCTION_IGNORE);
+ QVERIFY(findItem(completeSpy, "B")->_errorString.contains(expectedErrorString));
+
// The other folder should have been sync'ed as the sync just ignored the faulty dir
QCOMPARE(fakeFolder.currentRemoteState().children["A"], fakeFolder.currentLocalState().children["A"]);
QCOMPARE(fakeFolder.currentRemoteState().children["C"], fakeFolder.currentLocalState().children["C"]);
+ QCOMPARE(findItem(completeSpy, "A/z1")->_instruction, CSYNC_INSTRUCTION_NEW);
}
+
+ //
+ // Check the same discovery error on the sync root
+ //
+ errorFolder = "webdav/";
+ fatalErrorPrefix = "Server replied with an error while reading directory '' : ";
+ errorSpy.clear();
+ QVERIFY(!fakeFolder.syncOnce());
+ QCOMPARE(errorSpy.size(), 1);
+ QCOMPARE(errorSpy[0][0].toString(), QString(fatalErrorPrefix + expectedErrorString));
}
void testMissingData()