Forráskód Böngészése

ensure that bulk upload network job errors are handled

in case we get a network error during bulk propagator POST network
request, report all files within this upload as files in error that will
then be sent using the plain old WebDAV protocol

Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
Matthieu Gallien 4 éve
szülő
commit
e4590d7a3b
2 módosított fájl, 57 hozzáadás és 0 törlés
  1. 6 0
      src/libsync/bulkpropagatorjob.cpp
  2. 51 0
      test/testsyncengine.cpp

+ 6 - 0
src/libsync/bulkpropagatorjob.cpp

@@ -407,12 +407,18 @@ void BulkPropagatorJob::slotPutFinished()
 
     slotJobDestroyed(job); // remove it from the _jobs list
 
+    const auto jobError = job->reply()->error();
+
     const auto replyData = job->reply()->readAll();
     const auto replyJson = QJsonDocument::fromJson(replyData);
     const auto fullReplyObject = replyJson.object();
 
     for (const auto &singleFile : _filesToUpload) {
         if (!fullReplyObject.contains(singleFile._remotePath)) {
+            if (jobError != QNetworkReply::NoError) {
+                singleFile._item->_status = SyncFileItem::NormalError;
+                abortWithError(singleFile._item, SyncFileItem::NormalError, tr("Network Error: %1").arg(jobError));
+            }
             continue;
         }
         const auto singleReplyObject = fullReplyObject[singleFile._remotePath].toObject();

+ 51 - 0
test/testsyncengine.cpp

@@ -931,6 +931,57 @@ private slots:
         QCOMPARE(nPUT, 6);
         QCOMPARE(nPOST, 0);
     }
+
+    /**
+     * Checks whether subsequent large uploads are skipped after a 507 error
+     */
+    void testNetworkErrorsWithBulkUpload()
+    {
+        FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
+        fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ {"bulkupload", "1.0"} } } });
+
+        // Disable parallel uploads
+        SyncOptions syncOptions;
+        syncOptions._parallelNetworkJobs = 0;
+        fakeFolder.syncEngine().setSyncOptions(syncOptions);
+
+        int nPUT = 0;
+        int nPOST = 0;
+        fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *) -> QNetworkReply * {
+            auto contentType = request.header(QNetworkRequest::ContentTypeHeader).toString();
+            if (op == QNetworkAccessManager::PostOperation) {
+                ++nPOST;
+                if (contentType.startsWith(QStringLiteral("multipart/related; boundary="))) {
+                    return new FakeErrorReply(op, request, this, 400);
+                }
+                return  nullptr;
+            } else if (op == QNetworkAccessManager::PutOperation) {
+                ++nPUT;
+            }
+            return  nullptr;
+        });
+
+        fakeFolder.localModifier().insert("A/big1", 1);
+        fakeFolder.localModifier().insert("A/big2", 1);
+        fakeFolder.localModifier().insert("A/big3", 1);
+        fakeFolder.localModifier().insert("A/big4", 1);
+        fakeFolder.localModifier().insert("A/big5", 1);
+        fakeFolder.localModifier().insert("A/big6", 1);
+        fakeFolder.localModifier().insert("A/big7", 1);
+        fakeFolder.localModifier().insert("A/big8", 1);
+        fakeFolder.localModifier().insert("B/big8", 1);
+
+        QVERIFY(!fakeFolder.syncOnce());
+        QCOMPARE(nPUT, 0);
+        QCOMPARE(nPOST, 1);
+        nPUT = 0;
+        nPOST = 0;
+
+        QVERIFY(fakeFolder.syncOnce());
+        QCOMPARE(nPUT, 9);
+        QCOMPARE(nPOST, 0);
+        QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+    }
 };
 
 QTEST_GUILESS_MAIN(TestSyncEngine)