Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libsync/propagatedownload.cpp2
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/syncenginetestutils.h12
-rw-r--r--test/testdownload.cpp122
4 files changed, 133 insertions, 4 deletions
diff --git a/src/libsync/propagatedownload.cpp b/src/libsync/propagatedownload.cpp
index 77ce71386..ce8382618 100644
--- a/src/libsync/propagatedownload.cpp
+++ b/src/libsync/propagatedownload.cpp
@@ -612,7 +612,7 @@ void PropagateDownloadFile::slotGetFinished()
&propagator()->_anotherSyncNeeded);
}
- done(status, job->errorString());
+ done(status,_item->_httpErrorCode >= 400 ? job->errorStringParsingBody() : job->errorString());
return;
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 2df611817..0ba39105a 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -46,6 +46,7 @@ owncloud_add_test(SyncPlaceholders "syncenginetestutils.h")
owncloud_add_test(SyncMove "syncenginetestutils.h")
owncloud_add_test(SyncConflict "syncenginetestutils.h")
owncloud_add_test(SyncFileStatusTracker "syncenginetestutils.h")
+owncloud_add_test(Download "syncenginetestutils.h")
owncloud_add_test(ChunkingNg "syncenginetestutils.h")
owncloud_add_test(UploadReset "syncenginetestutils.h")
owncloud_add_test(AllFilesDeleted "syncenginetestutils.h")
diff --git a/test/syncenginetestutils.h b/test/syncenginetestutils.h
index 06c35d300..f07f93fda 100644
--- a/test/syncenginetestutils.h
+++ b/test/syncenginetestutils.h
@@ -715,8 +715,8 @@ class FakeErrorReply : public QNetworkReply
Q_OBJECT
public:
FakeErrorReply(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
- QObject *parent, int httpErrorCode)
- : QNetworkReply{parent}, _httpErrorCode(httpErrorCode) {
+ QObject *parent, int httpErrorCode, const QByteArray &body = QByteArray())
+ : QNetworkReply{parent}, _httpErrorCode(httpErrorCode), _body(body) {
setRequest(request);
setUrl(request.url());
setOperation(op);
@@ -732,9 +732,15 @@ public:
}
void abort() override { }
- qint64 readData(char *, qint64) override { return 0; }
+ qint64 readData(char *buf, qint64 max) override {
+ max = qMin<qint64>(max, _body.size());
+ memcpy(buf, _body.constData(), max);
+ _body = _body.mid(max);
+ return max;
+ }
int _httpErrorCode;
+ QByteArray _body;
};
// A reply that never responds
diff --git a/test/testdownload.cpp b/test/testdownload.cpp
new file mode 100644
index 000000000..4d9098e41
--- /dev/null
+++ b/test/testdownload.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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;
+
+static constexpr quint64 stopAfter = 3'123'668;
+
+/* A FakeGetReply that sends max 'fakeSize' bytes, but whose ContentLength has the corect size */
+class BrokenFakeGetReply : public FakeGetReply
+{
+ Q_OBJECT
+public:
+ using FakeGetReply::FakeGetReply;
+ int fakeSize = stopAfter;
+
+ qint64 bytesAvailable() const override
+ {
+ if (aborted)
+ return 0;
+ return std::min(size, fakeSize) + QIODevice::bytesAvailable();
+ }
+
+ qint64 readData(char *data, qint64 maxlen) override
+ {
+ qint64 len = std::min(qint64{ fakeSize }, maxlen);
+ std::fill_n(data, len, payload);
+ size -= len;
+ fakeSize -= len;
+ return len;
+ }
+};
+
+
+SyncFileItemPtr getItem(const QSignalSpy &spy, const QString &path)
+{
+ for (const QList<QVariant> &args : spy) {
+ auto item = args[0].value<SyncFileItemPtr>();
+ if (item->destination() == path)
+ return item;
+ }
+ return {};
+}
+
+
+class TestDownload : public QObject
+{
+ Q_OBJECT
+
+private slots:
+
+ void testResume()
+ {
+ FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
+ QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
+ auto size = 30 * 1000 * 1000;
+ fakeFolder.remoteModifier().insert("A/a0", size);
+
+ // First, download only the first 3 MB of the file
+ fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *) -> QNetworkReply * {
+ if (op == QNetworkAccessManager::GetOperation && request.url().path().endsWith("A/a0")) {
+ return new BrokenFakeGetReply(fakeFolder.remoteModifier(), op, request, this);
+ }
+ return nullptr;
+ });
+
+ QVERIFY(!fakeFolder.syncOnce()); // The sync must fail because not all the file was downloaded
+ QCOMPARE(getItem(completeSpy, "A/a0")->_status, SyncFileItem::SoftError);
+ QCOMPARE(getItem(completeSpy, "A/a0")->_errorString, QString("The file could not be downloaded completely."));
+ QVERIFY(fakeFolder.syncEngine().isAnotherSyncNeeded());
+
+ // Now, we need to restart, this time, it should resume.
+ QByteArray ranges;
+ fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *) -> QNetworkReply * {
+ if (op == QNetworkAccessManager::GetOperation && request.url().path().endsWith("A/a0")) {
+ ranges = request.rawHeader("Range");
+ }
+ return nullptr;
+ });
+ QVERIFY(fakeFolder.syncOnce()); // now this succeeds
+ QCOMPARE(ranges, QByteArray("bytes=" + QByteArray::number(stopAfter) + "-"));
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ }
+
+ void testErrorMessage () {
+ // This test's main goal is to test that the error string from the server is shown in the UI
+
+ FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
+ QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
+ auto size = 3'500'000;
+ fakeFolder.remoteModifier().insert("A/broken", size);
+
+ QByteArray serverMessage = "The file was not downloaded because the tests wants so!";
+
+ // First, download only the first 3 MB of the file
+ fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *) -> QNetworkReply * {
+ if (op == QNetworkAccessManager::GetOperation && request.url().path().endsWith("A/broken")) {
+ return new FakeErrorReply(op, request, this, 400,
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<d:error xmlns:d=\"DAV:\" xmlns:s=\"http://sabredav.org/ns\">\n"
+ "<s:exception>Sabre\\DAV\\Exception\\Forbidden</s:exception>\n"
+ "<s:message>"+serverMessage+"</s:message>\n"
+ "</d:error>");
+ }
+ return nullptr;
+ });
+
+ QVERIFY(!fakeFolder.syncOnce()); // Fail because A/broken
+ QCOMPARE(getItem(completeSpy, "A/broken")->_status, SyncFileItem::NormalError);
+ QVERIFY(getItem(completeSpy, "A/broken")->_errorString.contains(serverMessage));
+ }
+};
+
+QTEST_GUILESS_MAIN(TestDownload)
+#include "testdownload.moc"