2016-10-31 17:16:53 +03:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
2017-01-20 14:06:20 +03:00
|
|
|
/* Upload a 1/3 of a file of given size.
|
|
|
|
* fakeFolder needs to be synchronized */
|
|
|
|
static void partialUpload(FakeFolder &fakeFolder, const QString &name, int size)
|
|
|
|
{
|
|
|
|
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
|
|
|
QCOMPARE(fakeFolder.uploadState().children.count(), 0); // The state should be clean
|
|
|
|
|
|
|
|
fakeFolder.localModifier().insert(name, size);
|
|
|
|
// Abort when the upload is at 1/3
|
|
|
|
int sizeWhenAbort = -1;
|
|
|
|
auto con = QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::transmissionProgress,
|
|
|
|
[&](const ProgressInfo &progress) {
|
|
|
|
if (progress.completedSize() > (progress.totalSize() /3 )) {
|
|
|
|
sizeWhenAbort = progress.completedSize();
|
|
|
|
fakeFolder.syncEngine().abort();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
QVERIFY(!fakeFolder.syncOnce()); // there should have been an error
|
|
|
|
QObject::disconnect(con);
|
|
|
|
QVERIFY(sizeWhenAbort > 0);
|
|
|
|
QVERIFY(sizeWhenAbort < size);
|
|
|
|
|
|
|
|
QCOMPARE(fakeFolder.uploadState().children.count(), 1); // the transfer was done with chunking
|
|
|
|
auto upStateChildren = fakeFolder.uploadState().children.first().children;
|
|
|
|
QCOMPARE(sizeWhenAbort, std::accumulate(upStateChildren.cbegin(), upStateChildren.cend(), 0,
|
|
|
|
[](int s, const FileInfo &i) { return s + i.size; }));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-31 17:16:53 +03:00
|
|
|
class TestChunkingNG : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
|
|
|
|
void testFileUpload() {
|
|
|
|
FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
|
|
|
|
fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ {"chunking", "1.0"} } } });
|
|
|
|
const int size = 300 * 1000 * 1000; // 300 MB
|
|
|
|
fakeFolder.localModifier().insert("A/a0", size);
|
|
|
|
QVERIFY(fakeFolder.syncOnce());
|
|
|
|
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
|
|
|
QCOMPARE(fakeFolder.uploadState().children.count(), 1); // the transfer was done with chunking
|
2016-10-31 19:44:00 +03:00
|
|
|
QCOMPARE(fakeFolder.currentRemoteState().find("A/a0")->size, size);
|
2016-10-31 17:16:53 +03:00
|
|
|
|
|
|
|
// Check that another upload of the same file also work.
|
|
|
|
fakeFolder.localModifier().appendByte("A/a0");
|
|
|
|
QVERIFY(fakeFolder.syncOnce());
|
|
|
|
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
|
|
|
QCOMPARE(fakeFolder.uploadState().children.count(), 2); // the transfer was done with chunking
|
|
|
|
}
|
2016-10-31 19:44:00 +03:00
|
|
|
|
|
|
|
|
|
|
|
void testResume () {
|
|
|
|
|
|
|
|
FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
|
|
|
|
fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ {"chunking", "1.0"} } } });
|
|
|
|
const int size = 300 * 1000 * 1000; // 300 MB
|
2017-01-20 14:06:20 +03:00
|
|
|
partialUpload(fakeFolder, "A/a0", size);
|
|
|
|
QCOMPARE(fakeFolder.uploadState().children.count(), 1);
|
|
|
|
auto chunkingId = fakeFolder.uploadState().children.first().name;
|
2016-10-31 19:44:00 +03:00
|
|
|
|
|
|
|
// Add a fake file to make sure it gets deleted
|
|
|
|
fakeFolder.uploadState().children.first().insert("10000", size);
|
|
|
|
QVERIFY(fakeFolder.syncOnce());
|
|
|
|
|
2017-01-20 14:06:20 +03:00
|
|
|
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
|
|
|
QCOMPARE(fakeFolder.currentRemoteState().find("A/a0")->size, size);
|
|
|
|
// The same chunk id was re-used
|
|
|
|
QCOMPARE(fakeFolder.uploadState().children.count(), 1);
|
|
|
|
QCOMPARE(fakeFolder.uploadState().children.first().name, chunkingId);
|
|
|
|
}
|
2016-10-31 19:44:00 +03:00
|
|
|
|
2017-01-20 14:06:20 +03:00
|
|
|
// We modify the file locally after it has been partially uploaded
|
|
|
|
void testRemoveStale() {
|
|
|
|
|
|
|
|
FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
|
|
|
|
fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ {"chunking", "1.0"} } } });
|
|
|
|
const int size = 300 * 1000 * 1000; // 300 MB
|
|
|
|
partialUpload(fakeFolder, "A/a0", size);
|
|
|
|
QCOMPARE(fakeFolder.uploadState().children.count(), 1);
|
|
|
|
auto chunkingId = fakeFolder.uploadState().children.first().name;
|
|
|
|
|
|
|
|
|
|
|
|
fakeFolder.localModifier().setContents("A/a0", 'B');
|
|
|
|
fakeFolder.localModifier().appendByte("A/a0");
|
|
|
|
|
|
|
|
QVERIFY(fakeFolder.syncOnce());
|
2016-10-31 19:44:00 +03:00
|
|
|
|
|
|
|
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
2017-01-20 14:06:20 +03:00
|
|
|
QCOMPARE(fakeFolder.currentRemoteState().find("A/a0")->size, size + 1);
|
|
|
|
// A different chunk id was used, and the previous one is removed
|
|
|
|
QCOMPARE(fakeFolder.uploadState().children.count(), 1);
|
|
|
|
QVERIFY(fakeFolder.uploadState().children.first().name != chunkingId);
|
2016-10-31 19:44:00 +03:00
|
|
|
}
|
2016-10-31 17:16:53 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
QTEST_GUILESS_MAIN(TestChunkingNG)
|
|
|
|
#include "testchunkingng.moc"
|