diff options
author | Erik Verbruggen <erik@verbruggen.consulting> | 2022-09-08 18:57:43 +0300 |
---|---|---|
committer | Erik Verbruggen <Erik.Verbruggen@Me.com> | 2022-09-22 17:21:51 +0300 |
commit | c60da8be5dfca5b232440f30657098823c822d68 (patch) | |
tree | 1bd8b5373c615fc1be26bc49cc2fc96fc284e42c /test | |
parent | fe3136a1b68f5efad414944655c310e2992879de (diff) |
Tests: Clean up FileModifier API
- make the default values into static constexpr member fields
- remove unused method `modifyByte`
- don't rely on on-disk info like file sizes (so it can be used in
dehydrated VFS modes)
Diffstat (limited to 'test')
-rw-r--r-- | test/testallfilesdeleted.cpp | 20 | ||||
-rw-r--r-- | test/testblacklist.cpp | 7 | ||||
-rw-r--r-- | test/testchunkingng.cpp | 56 | ||||
-rw-r--r-- | test/testdownload.cpp | 5 | ||||
-rw-r--r-- | test/testpermissions.cpp | 4 | ||||
-rw-r--r-- | test/testsyncconflict.cpp | 16 | ||||
-rw-r--r-- | test/testsyncengine.cpp | 21 | ||||
-rw-r--r-- | test/testsyncmove.cpp | 29 | ||||
-rw-r--r-- | test/testutils/syncenginetestutils.cpp | 41 | ||||
-rw-r--r-- | test/testutils/syncenginetestutils.h | 66 |
10 files changed, 149 insertions, 116 deletions
diff --git a/test/testallfilesdeleted.cpp b/test/testallfilesdeleted.cpp index bd220457c..7b78749f1 100644 --- a/test/testallfilesdeleted.cpp +++ b/test/testallfilesdeleted.cpp @@ -67,9 +67,10 @@ private slots: }); auto &modifier = deleteOnRemote ? fakeFolder.remoteModifier() : fakeFolder.localModifier(); - const auto &children = fakeFolder.currentRemoteState().children; - for (auto it = children.cbegin(); it != children.cend(); ++it) + const auto children = fakeFolder.currentRemoteState().children; // make sure to take a copy, otherwise it's a use-after-free + for (auto it = children.cbegin(); it != children.cend(); ++it) { modifier.remove(it.key()); + } QVERIFY(!fakeFolder.syncOnce()); // Should fail because we cancel the sync QCOMPARE(aboutToRemoveAllFilesCalled, 1); @@ -108,9 +109,10 @@ private slots: }); auto &modifier = deleteOnRemote ? fakeFolder.remoteModifier() : fakeFolder.localModifier(); - const auto &children = fakeFolder.currentRemoteState().children; - for (auto it = children.cbegin(); it != children.cend(); ++it) + const auto children = fakeFolder.currentRemoteState().children; // make sure to take a copy, otherwise it's a use-after-free + for (auto it = children.cbegin(); it != children.cend(); ++it) { modifier.remove(it.key()); + } QVERIFY(fakeFolder.syncOnce()); // Should succeed, and all files must then be deleted @@ -187,18 +189,18 @@ private slots: } - void testDataFingetPrint_data() + void testDataFingerPrint_data() { QTest::addColumn<bool>("hasInitialFingerPrint"); QTest::newRow("initial finger print") << true; QTest::newRow("no initial finger print") << false; } - void testDataFingetPrint() + void testDataFingerPrint() { QFETCH(bool, hasInitialFingerPrint); FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; - fakeFolder.remoteModifier().setContents(QStringLiteral("C/c1"), 'N'); + fakeFolder.remoteModifier().setContents(QStringLiteral("C/c1"), FileModifier::DefaultFileSize, 'N'); fakeFolder.remoteModifier().setModTime(QStringLiteral("C/c1"), QDateTime::currentDateTimeUtc().addDays(-2)); fakeFolder.remoteModifier().remove(QStringLiteral("C/c2")); if (hasInitialFingerPrint) { @@ -234,12 +236,12 @@ private slots: /* Simulate a backup restoration */ // A/a1 is an old file - fakeFolder.remoteModifier().setContents(QStringLiteral("A/a1"), 'O'); + fakeFolder.remoteModifier().setContents(QStringLiteral("A/a1"), FileModifier::DefaultFileSize, 'O'); fakeFolder.remoteModifier().setModTime(QStringLiteral("A/a1"), QDateTime::currentDateTimeUtc().addDays(-2)); // B/b1 did not exist at the time of the backup fakeFolder.remoteModifier().remove(QStringLiteral("B/b1")); // B/b2 was uploaded by another user in the mean time. - fakeFolder.remoteModifier().setContents(QStringLiteral("B/b2"), 'N'); + fakeFolder.remoteModifier().setContents(QStringLiteral("B/b2"), FileModifier::DefaultFileSize, 'N'); fakeFolder.remoteModifier().setModTime(QStringLiteral("B/b2"), QDateTime::currentDateTimeUtc().addDays(2)); // C/c3 was removed since we made the backup diff --git a/test/testblacklist.cpp b/test/testblacklist.cpp index 4c16c0703..2585b1335 100644 --- a/test/testblacklist.cpp +++ b/test/testblacklist.cpp @@ -79,8 +79,9 @@ private slots: QVERIFY(entry._ignoreDuration > 0); QCOMPARE(entry._requestId, reqId); - if (remote) + if (remote) { QCOMPARE(journalRecord(fakeFolder, "A")._etag, initialEtag); + } } cleanup(); @@ -132,6 +133,10 @@ private slots: } cleanup(); + // Try to make sure that the modifications below do are not within the same second as the + // previous sync attempt was done, otherwise the changes go undetected. + QThread::sleep(1); + // When the file changes a retry happens immediately modifier.appendByte(testFileName); QVERIFY(!fakeFolder.syncOnce()); diff --git a/test/testchunkingng.cpp b/test/testchunkingng.cpp index 65f4040bc..bba9329d3 100644 --- a/test/testchunkingng.cpp +++ b/test/testchunkingng.cpp @@ -15,6 +15,22 @@ using namespace std::chrono_literals; using namespace OCC; namespace { + +constexpr unsigned long long operator"" _kb(unsigned long long sz) +{ + return sz * 1024; +} + +constexpr unsigned long long operator"" _mb(unsigned long long sz) +{ + return operator"" _kb(sz) * 1024; +} + +constexpr unsigned long long operator"" _gb(unsigned long long sz) +{ + return operator"" _mb(sz) * 1024; +} + /* Upload a 1/3 of a file of given size. * fakeFolder needs to be synchronized */ void partialUpload(FakeFolder &fakeFolder, const QString &name, qint64 size) @@ -52,7 +68,8 @@ void setChunkSize(SyncEngine &engine, qint64 size) options._minChunkSize = size; engine.setSyncOptions(options); } -} + +} // anonymous namespace class TestChunkingNG : public QObject { @@ -367,9 +384,9 @@ private slots: QCOMPARE(fakeFolder.uploadState().children.count(), 1); auto chunkingId = fakeFolder.uploadState().children.first().name; - - fakeFolder.localModifier().setContents(QStringLiteral("A/a0"), 'B'); - fakeFolder.localModifier().appendByte(QStringLiteral("A/a0")); + const auto a0size = fakeFolder.currentLocalState().find("A/a0")->contentSize; + fakeFolder.localModifier().setContents(QStringLiteral("A/a0"), a0size, 'B'); + fakeFolder.localModifier().appendByte(QStringLiteral("A/a0"), 'B'); QVERIFY(fakeFolder.syncOnce()); @@ -408,16 +425,17 @@ private slots: QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); // Modify the file localy and start the upload - fakeFolder.localModifier().setContents(QStringLiteral("A/a0"), 'B'); - fakeFolder.localModifier().appendByte(QStringLiteral("A/a0")); + fakeFolder.localModifier().setContents(QStringLiteral("A/a0"), size, 'B'); + fakeFolder.localModifier().appendByte(QStringLiteral("A/a0"), 'B'); // But in the middle of the sync, modify the file on the server - QMetaObject::Connection con = QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::transmissionProgress, - [&](const ProgressInfo &progress) { - if (progress.completedSize() > (progress.totalSize() / 2 )) { - fakeFolder.remoteModifier().setContents(QStringLiteral("A/a0"), 'C'); - QObject::disconnect(con); - } + QMetaObject::Connection con = QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::transmissionProgress, [&](const ProgressInfo &progress) { + qDebug() << progress.completedSize() << progress.totalSize(); + if (progress.completedSize() > (progress.totalSize() / 2)) { + auto a0size = fakeFolder.currentRemoteState().find(QStringLiteral("A/a0"))->contentSize; + fakeFolder.remoteModifier().setContents(QStringLiteral("A/a0"), a0size, 'C'); + QObject::disconnect(con); + } }); QVERIFY(!fakeFolder.syncOnce()); @@ -455,17 +473,17 @@ private slots: void testModifyLocalFileWhileUploading() { FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()}; - const int size = 10 * 1000 * 1000; // 100 MB - setChunkSize(fakeFolder.syncEngine(), 1 * 1000 * 1000); + const int size = 10_mb; + setChunkSize(fakeFolder.syncEngine(), 1_mb); - fakeFolder.localModifier().insert(QStringLiteral("A/a0"), size); + fakeFolder.localModifier().insert(QStringLiteral("A/a0"), size, 'A'); // middle of the sync, modify the file QMetaObject::Connection con = QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::transmissionProgress, [&](const ProgressInfo &progress) { if (progress.completedSize() > (progress.totalSize() / 2 )) { - fakeFolder.localModifier().setContents(QStringLiteral("A/a0"), 'B'); - fakeFolder.localModifier().appendByte(QStringLiteral("A/a0")); + fakeFolder.localModifier().setContents(QStringLiteral("A/a0"), size, 'B'); + fakeFolder.localModifier().appendByte(QStringLiteral("A/a0"), 'B'); QObject::disconnect(con); } }); @@ -591,10 +609,10 @@ private slots: QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); } - // Test uploading large files (2.5GiB) + // Test uploading large files (2 GiB) void testVeryBigFiles() { FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()}; - const qint64 size = 2.5 * 1024 * 1024 * 1024; // 2.5 GiB + const qint64 size = 2_gb; // stay under the INT_MAX limit: QByteArray takes a signed int, so bigger sizes will give weird results. // Partial upload of big files partialUpload(fakeFolder, QStringLiteral("A/a0"), size); diff --git a/test/testdownload.cpp b/test/testdownload.cpp index 492f0ebbe..89add9b06 100644 --- a/test/testdownload.cpp +++ b/test/testdownload.cpp @@ -174,8 +174,9 @@ private slots: FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; fakeFolder.syncEngine().setIgnoreHiddenFiles(true); - fakeFolder.remoteModifier().setContents(QStringLiteral("A/a1"), 'A'); - fakeFolder.localModifier().setContents(QStringLiteral("A/a1"), 'B'); + fakeFolder.account()->setCapabilities(TestUtils::testCapabilities(CheckSums::Algorithm::ADLER32)); + fakeFolder.remoteModifier().setContents(QStringLiteral("A/a1"), FileModifier::DefaultFileSize, 'A'); + fakeFolder.localModifier().setContents(QStringLiteral("A/a1"), FileModifier::DefaultFileSize, 'B'); bool propConnected = false; QString conflictFile; diff --git a/test/testpermissions.cpp b/test/testpermissions.cpp index 5340886c1..8e4242078 100644 --- a/test/testpermissions.cpp +++ b/test/testpermissions.cpp @@ -313,7 +313,7 @@ private slots: QVERIFY(fakeFolder.syncOnce()); editReadOnly(QStringLiteral("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data")); - fakeFolder.localModifier().setContents(QStringLiteral("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data"), 's'); + fakeFolder.localModifier().setContents(QStringLiteral("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data"), FileModifier::DefaultFileSize, 's'); //do the sync applyPermissionsFromName(fakeFolder.remoteModifier()); QVERIFY(fakeFolder.syncOnce()); @@ -321,7 +321,7 @@ private slots: QThread::sleep(1); // make sure changes have different mtime editReadOnly(QStringLiteral("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data")); - fakeFolder.localModifier().setContents(QStringLiteral("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data"), 'd'); + fakeFolder.localModifier().setContents(QStringLiteral("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data"), FileModifier::DefaultFileSize, 'd'); //do the sync applyPermissionsFromName(fakeFolder.remoteModifier()); diff --git a/test/testsyncconflict.cpp b/test/testsyncconflict.cpp index fd8f84ee7..b74bf708d 100644 --- a/test/testsyncconflict.cpp +++ b/test/testsyncconflict.cpp @@ -86,8 +86,8 @@ private slots: FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); - fakeFolder.localModifier().setContents(QStringLiteral("A/a1"), 'L'); - fakeFolder.remoteModifier().setContents(QStringLiteral("A/a1"), 'R'); + fakeFolder.localModifier().setContents(QStringLiteral("A/a1"), FileModifier::DefaultFileSize, 'L'); + fakeFolder.remoteModifier().setContents(QStringLiteral("A/a1"), FileModifier::DefaultFileSize, 'R'); fakeFolder.localModifier().appendByte(QStringLiteral("A/a2")); fakeFolder.remoteModifier().appendByte(QStringLiteral("A/a2")); fakeFolder.remoteModifier().appendByte(QStringLiteral("A/a2")); @@ -129,8 +129,8 @@ private slots: return nullptr; }); - fakeFolder.localModifier().setContents(QStringLiteral("A/a1"), 'L'); - fakeFolder.remoteModifier().setContents(QStringLiteral("A/a1"), 'R'); + fakeFolder.localModifier().setContents(QStringLiteral("A/a1"), FileModifier::DefaultFileSize, 'L'); + fakeFolder.remoteModifier().setContents(QStringLiteral("A/a1"), FileModifier::DefaultFileSize, 'R'); fakeFolder.localModifier().appendByte(QStringLiteral("A/a2")); fakeFolder.remoteModifier().appendByte(QStringLiteral("A/a2")); fakeFolder.remoteModifier().appendByte(QStringLiteral("A/a2")); @@ -200,7 +200,7 @@ private slots: // Now the user can locally alter the conflict file and it will be uploaded // as usual. - fakeFolder.localModifier().setContents(conflictName, 'P'); + fakeFolder.localModifier().setContents(conflictName, FileModifier::DefaultFileSize + 1, 'P'); // make sure the file sizes are different QVERIFY(fakeFolder.syncOnce()); QCOMPARE(conflictMap.size(), 1); QCOMPARE(conflictMap[a1FileId], conflictName); @@ -208,7 +208,7 @@ private slots: conflictMap.clear(); // Similarly, remote modifications of conflict files get propagated downwards - fakeFolder.remoteModifier().setContents(conflictName, 'Q'); + fakeFolder.remoteModifier().setContents(conflictName, FileModifier::DefaultFileSize + 1, 'Q'); // make sure the file sizes are different QVERIFY(fakeFolder.syncOnce()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QVERIFY(conflictMap.isEmpty()); @@ -222,8 +222,8 @@ private slots: QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QCOMPARE(conflictMap.size(), 1); QVERIFY(conflictMap.contains(a1ConflictFileId)); - QCOMPARE(fakeFolder.currentRemoteState().find(conflictName)->contentSize, 66); - QCOMPARE(fakeFolder.currentRemoteState().find(conflictMap[a1ConflictFileId])->contentSize, 65); + QCOMPARE(fakeFolder.currentRemoteState().find(conflictName)->contentSize, FileModifier::DefaultFileSize + 3); + QCOMPARE(fakeFolder.currentRemoteState().find(conflictMap[a1ConflictFileId])->contentSize, FileModifier::DefaultFileSize + 2); conflictMap.clear(); } diff --git a/test/testsyncengine.cpp b/test/testsyncengine.cpp index cba272515..3d6a0ed91 100644 --- a/test/testsyncengine.cpp +++ b/test/testsyncengine.cpp @@ -134,16 +134,16 @@ private slots: ItemCompletedSpy completeSpy(fakeFolder); // Touch the file without changing the content, shouldn't upload - fakeFolder.localModifier().setContents(QStringLiteral("a1.eml"), 'A'); + fakeFolder.localModifier().setContents(QStringLiteral("a1.eml"), 64, 'A'); // Change the content/size - fakeFolder.localModifier().setContents(QStringLiteral("a2.eml"), 'B'); - fakeFolder.localModifier().appendByte(QStringLiteral("a3.eml")); - fakeFolder.localModifier().appendByte(QStringLiteral("b3.txt")); + fakeFolder.localModifier().setContents(QStringLiteral("a2.eml"), 64, 'B'); + fakeFolder.localModifier().appendByte(QStringLiteral("a3.eml"), 'X'); + fakeFolder.localModifier().appendByte(QStringLiteral("b3.txt"), 'X'); fakeFolder.syncOnce(); QCOMPARE(getDbChecksum("a1.eml"), referenceChecksum); QCOMPARE(getDbChecksum("a2.eml"), QByteArray("SHA1:84951fc23a4dafd10020ac349da1f5530fa65949")); - QCOMPARE(getDbChecksum("a3.eml"), QByteArray("SHA1:826b7e7a7af8a529ae1c7443c23bf185c0ad440c")); + QCOMPARE(getDbChecksum("a3.eml"), QByteArray("SHA1:c119308d57884896cd86a7050e449aaba24b1fee")); QCOMPARE(getDbChecksum("b3.eml"), getDbChecksum("a3.txt")); QVERIFY(!itemDidComplete(completeSpy, "a1.eml")); @@ -356,11 +356,13 @@ private slots: auto mtime = QDateTime::currentDateTimeUtc().addDays(-4); mtime.setMSecsSinceEpoch(mtime.toMSecsSinceEpoch() / 1000 * 1000); - fakeFolder.localModifier().setContents(QStringLiteral("A/a1"), 'C'); + const auto a1size = fakeFolder.currentLocalState().find("A/a1")->contentSize; + fakeFolder.localModifier().setContents(QStringLiteral("A/a1"), a1size, 'C'); fakeFolder.localModifier().setModTime(QStringLiteral("A/a1"), mtime); - fakeFolder.remoteModifier().setContents(QStringLiteral("A/a1"), 'C'); - if (!sameMtime) + fakeFolder.remoteModifier().setContents(QStringLiteral("A/a1"), a1size, 'C'); + if (!sameMtime) { mtime = mtime.addDays(1); + } fakeFolder.remoteModifier().setModTime(QStringLiteral("A/a1"), mtime); remoteInfo.find("A/a1")->checksums = checksums; QVERIFY(fakeFolder.syncOnce()); @@ -398,8 +400,7 @@ private slots: initialFileInfo.setModTime(QStringLiteral("B/b1"), initialMtime); initialFileInfo.setModTime(QStringLiteral("C/c1"), initialMtime); - FakeFolder fakeFolder{ initialFileInfo }; - + FakeFolder fakeFolder(initialFileInfo); // upload a fakeFolder.localModifier().appendByte(QStringLiteral("A/a1")); diff --git a/test/testsyncmove.cpp b/test/testsyncmove.cpp index c0c238b07..400b0456a 100644 --- a/test/testsyncmove.cpp +++ b/test/testsyncmove.cpp @@ -224,8 +224,9 @@ private slots: // Move-and-change, content only -- c1 has no checksum, so we fail to detect this! // NOTE: This is an expected failure. mtime = fakeFolder.remoteModifier().find("C/c1")->lastModified(); + auto size = fakeFolder.currentRemoteState().find("C/c1")->contentSize; fakeFolder.localModifier().rename(QStringLiteral("C/c1"), QStringLiteral("C/c1m")); - fakeFolder.localModifier().setContents(QStringLiteral("C/c1m"), 'C'); + fakeFolder.localModifier().setContents(QStringLiteral("C/c1m"), size, 'C'); fakeFolder.localModifier().setModTime(QStringLiteral("C/c1m"), mtime); QVERIFY(fakeFolder.syncOnce()); QCOMPARE(nPUT, 3); @@ -244,7 +245,7 @@ private slots: // Move-and-change, content only, this time while having a checksum mtime = fakeFolder.remoteModifier().find("C/c3")->lastModified(); fakeFolder.localModifier().rename(QStringLiteral("C/c3"), QStringLiteral("C/c3m")); - fakeFolder.localModifier().setContents(QStringLiteral("C/c3m"), 'C'); + fakeFolder.localModifier().setContents(QStringLiteral("C/c3m"), FileModifier::DefaultFileSize, 'C'); fakeFolder.localModifier().setModTime(QStringLiteral("C/c3m"), mtime); QVERIFY(fakeFolder.syncOnce()); QCOMPARE(nPUT, 5); @@ -363,9 +364,9 @@ private slots: // Touch+Move on same side counter.reset(); local.rename(QStringLiteral("A/a2"), QStringLiteral("A/a2m")); - local.setContents(QStringLiteral("A/a2m"), 'A'); + local.setContents(QStringLiteral("A/a2m"), FileModifier::DefaultFileSize, 'A'); remote.rename(QStringLiteral("B/b2"), QStringLiteral("B/b2m")); - remote.setContents(QStringLiteral("B/b2m"), 'A'); + remote.setContents(QStringLiteral("B/b2m"), FileModifier::DefaultFileSize, 'A'); QVERIFY(fakeFolder.syncOnce()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QCOMPARE(printDbData(fakeFolder.dbState()), printDbData(fakeFolder.currentRemoteState())); @@ -379,9 +380,9 @@ private slots: // Touch+Move on opposite sides counter.reset(); local.rename(QStringLiteral("A/a1m"), QStringLiteral("A/a1m2")); - remote.setContents(QStringLiteral("A/a1m"), 'B'); + remote.setContents(QStringLiteral("A/a1m"), FileModifier::DefaultFileSize, 'B'); remote.rename(QStringLiteral("B/b1m"), QStringLiteral("B/b1m2")); - local.setContents(QStringLiteral("B/b1m"), 'B'); + local.setContents(QStringLiteral("B/b1m"), FileModifier::DefaultFileSize, 'B'); QVERIFY(fakeFolder.syncOnce()); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QCOMPARE(printDbData(fakeFolder.dbState()), printDbData(fakeFolder.currentRemoteState())); @@ -496,14 +497,14 @@ private slots: // Folder move with contents touched on the same side { counter.reset(); - local.setContents(QStringLiteral("AM/a2m"), 'C'); + local.setContents(QStringLiteral("AM/a2m"), FileModifier::DefaultFileSize, 'C'); // We must change the modtime for it is likely that it did not change between sync. // (Previous version of the client (<=2.5) would not need this because it was always doing // checksum comparison for all renames. But newer version no longer does it if the file is // renamed because the parent folder is renamed) local.setModTime(QStringLiteral("AM/a2m"), QDateTime::currentDateTimeUtc().addDays(3)); local.rename(QStringLiteral("AM"), QStringLiteral("A2")); - remote.setContents(QStringLiteral("BM/b2m"), 'C'); + remote.setContents(QStringLiteral("BM/b2m"), FileModifier::DefaultFileSize, 'C'); remote.rename(QStringLiteral("BM"), QStringLiteral("B2")); ItemCompletedSpy completeSpy(fakeFolder); QVERIFY(fakeFolder.syncOnce()); @@ -521,12 +522,12 @@ private slots: // Folder rename with contents touched on the other tree counter.reset(); - remote.setContents(QStringLiteral("A2/a2m"), 'D'); + remote.setContents(QStringLiteral("A2/a2m"), FileModifier::DefaultFileSize, 'D'); // setContents alone may not produce updated mtime if the test is fast // and since we don't use checksums here, that matters. remote.appendByte(QStringLiteral("A2/a2m")); local.rename(QStringLiteral("A2"), QStringLiteral("A3")); - local.setContents(QStringLiteral("B2/b2m"), 'D'); + local.setContents(QStringLiteral("B2/b2m"), FileModifier::DefaultFileSize, 'D'); local.appendByte(QStringLiteral("B2/b2m")); remote.rename(QStringLiteral("B2"), QStringLiteral("B3")); QVERIFY(fakeFolder.syncOnce()); @@ -541,15 +542,15 @@ private slots: // Folder rename with contents touched on both ends counter.reset(); - remote.setContents(QStringLiteral("A3/a2m"), 'R'); + remote.setContents(QStringLiteral("A3/a2m"), FileModifier::DefaultFileSize, 'R'); remote.appendByte(QStringLiteral("A3/a2m")); - local.setContents(QStringLiteral("A3/a2m"), 'L'); + local.setContents(QStringLiteral("A3/a2m"), FileModifier::DefaultFileSize, 'L'); local.appendByte(QStringLiteral("A3/a2m")); local.appendByte(QStringLiteral("A3/a2m")); local.rename(QStringLiteral("A3"), QStringLiteral("A4")); - remote.setContents(QStringLiteral("B3/b2m"), 'R'); + remote.setContents(QStringLiteral("B3/b2m"), FileModifier::DefaultFileSize, 'R'); remote.appendByte(QStringLiteral("B3/b2m")); - local.setContents(QStringLiteral("B3/b2m"), 'L'); + local.setContents(QStringLiteral("B3/b2m"), FileModifier::DefaultFileSize, 'L'); local.appendByte(QStringLiteral("B3/b2m")); local.appendByte(QStringLiteral("B3/b2m")); remote.rename(QStringLiteral("B3"), QStringLiteral("B4")); diff --git a/test/testutils/syncenginetestutils.cpp b/test/testutils/syncenginetestutils.cpp index 0b67f671b..6f853d514 100644 --- a/test/testutils/syncenginetestutils.cpp +++ b/test/testutils/syncenginetestutils.cpp @@ -48,7 +48,7 @@ void DiskFileModifier::remove(const QString &relativePath) QVERIFY(QDir { fi.filePath() }.removeRecursively()); } -void DiskFileModifier::insert(const QString &relativePath, qint64 size, char contentChar) +void DiskFileModifier::insert(const QString &relativePath, quint64 size, char contentChar) { QFile file { _rootDir.filePath(relativePath) }; QVERIFY(!file.exists()); @@ -64,13 +64,12 @@ void DiskFileModifier::insert(const QString &relativePath, qint64 size, char con QCOMPARE(file.size(), size); } -void DiskFileModifier::setContents(const QString &relativePath, char contentChar) +void DiskFileModifier::setContents(const QString &relativePath, quint64 newSize, char contentChar) { QFile file { _rootDir.filePath(relativePath) }; QVERIFY(file.exists()); - qint64 size = file.size(); file.open(QFile::WriteOnly); - file.write(QByteArray {}.fill(contentChar, size)); + file.write(QByteArray {}.fill(contentChar, newSize)); } void DiskFileModifier::appendByte(const QString &relativePath, char contentChar) @@ -87,16 +86,6 @@ void DiskFileModifier::appendByte(const QString &relativePath, char contentChar) file.write(contents); } -void DiskFileModifier::modifyByte(const QString &relativePath, quint64 offset, char contentChar) -{ - QFile file { _rootDir.filePath(relativePath) }; - QVERIFY(file.exists()); - file.open(QFile::ReadWrite); - file.seek(offset); - file.write(&contentChar, 1); - file.close(); -} - void DiskFileModifier::mkdir(const QString &relativePath) { _rootDir.mkpath(relativePath); @@ -152,21 +141,25 @@ void FileInfo::remove(const QString &relativePath) [&pathComponents](const FileInfo &fi) { return fi.name == pathComponents.fileName(); })); } -void FileInfo::insert(const QString &relativePath, qint64 size, char contentChar) +void FileInfo::insert(const QString &relativePath, quint64 size, char contentChar) { create(relativePath, size, contentChar); } -void FileInfo::setContents(const QString &relativePath, char contentChar) +void FileInfo::setContents(const QString &relativePath, quint64 newSize, char contentChar) { FileInfo *file = findInvalidatingEtags(relativePath); Q_ASSERT(file); file->contentChar = contentChar; + file->contentSize = newSize; + if (!file->isDehydratedPlaceholder) { + file->fileSize = newSize; + } } void FileInfo::appendByte(const QString &relativePath, char contentChar) { - Q_UNUSED(contentChar); + Q_UNUSED(contentChar) FileInfo *file = findInvalidatingEtags(relativePath); Q_ASSERT(file); if (!file->isDehydratedPlaceholder) { @@ -175,15 +168,6 @@ void FileInfo::appendByte(const QString &relativePath, char contentChar) file->fileSize += 1; } -void FileInfo::modifyByte(const QString &relativePath, quint64 offset, char contentChar) -{ - Q_UNUSED(offset); - Q_UNUSED(contentChar); - FileInfo *file = findInvalidatingEtags(relativePath); - Q_ASSERT(file); - Q_ASSERT(!"unimplemented"); -} - void FileInfo::mkdir(const QString &relativePath) { createDir(relativePath); @@ -244,7 +228,7 @@ FileInfo *FileInfo::createDir(const QString &relativePath) return &child; } -FileInfo *FileInfo::create(const QString &relativePath, qint64 size, char contentChar) +FileInfo *FileInfo::create(const QString &relativePath, quint64 size, char contentChar) { const PathComponents pathComponents { relativePath }; FileInfo *parent = findInvalidatingEtags(pathComponents.parentDirComponents()); @@ -1106,9 +1090,10 @@ void FakeFolder::fromDisk(QDir &dir, FileInfo &templateFi) fi.setLastModified(diskChild.lastModified()); if (fi.isDehydratedPlaceholder) { fi.contentChar = '\0'; + fi.contentSize = 0; } else { QFile f { diskChild.filePath() }; - f.open(QFile::ReadOnly); + OC_ENFORCE(f.open(QFile::ReadOnly)); auto content = f.read(1); if (content.size() == 0) { qWarning() << "Empty file at:" << diskChild.filePath(); diff --git a/test/testutils/syncenginetestutils.h b/test/testutils/syncenginetestutils.h index e06f09bda..a8e445d60 100644 --- a/test/testutils/syncenginetestutils.h +++ b/test/testutils/syncenginetestutils.h @@ -78,15 +78,21 @@ public: QString fileName() const { return last(); } }; +/** + * @brief The FileModifier class defines the interface for both the local on-disk modifier and the + * remote in-memory modifier. + */ class FileModifier { public: + static constexpr int DefaultFileSize = 64; + static constexpr char DefaultContentChar = 'X'; + virtual ~FileModifier() { } virtual void remove(const QString &relativePath) = 0; - virtual void insert(const QString &relativePath, qint64 size = 64, char contentChar = 'W') = 0; - virtual void setContents(const QString &relativePath, char contentChar) = 0; - virtual void appendByte(const QString &relativePath, char contentChar = 0) = 0; - virtual void modifyByte(const QString &relativePath, quint64 offset, char contentChar) = 0; + virtual void insert(const QString &relativePath, quint64 size = DefaultFileSize, char contentChar = DefaultContentChar) = 0; + virtual void setContents(const QString &relativePath, quint64 newSize, char contentChar = DefaultContentChar) = 0; + virtual void appendByte(const QString &relativePath, char contentChar = DefaultContentChar) = 0; virtual void mkdir(const QString &relativePath) = 0; virtual void rename(const QString &relativePath, const QString &relativeDestinationDirectory) = 0; virtual void setModTime(const QString &relativePath, const QDateTime &modTime) = 0; @@ -102,10 +108,9 @@ public: { } void remove(const QString &relativePath) override; - void insert(const QString &relativePath, qint64 size = 64, char contentChar = 'W') override; - void setContents(const QString &relativePath, char contentChar) override; - void appendByte(const QString &relativePath, char contentChar) override; - void modifyByte(const QString &relativePath, quint64 offset, char contentChar) override; + void insert(const QString &relativePath, quint64 size = DefaultFileSize, char contentChar = DefaultContentChar) override; + void setContents(const QString &relativePath, quint64 newSize, char contentChar = DefaultContentChar) override; + void appendByte(const QString &relativePath, char contentChar = DefaultContentChar) override; void mkdir(const QString &relativePath) override; void rename(const QString &from, const QString &to) override; @@ -119,9 +124,17 @@ static inline qint64 defaultLastModified() return timeInSeconds; } -/// FIXME: we should make it explicit in the construtor if we're talking about a hydrated or a dehydrated file! +/** + * @brief The FileInfo class represents the remotely stored (on-server) content. To be able to + * modify the content, this class is also the remote \c FileModifier. + */ class FileInfo : public FileModifier { + /// FIXME: we should make it explicit in the construtor if we're talking about a hydrated or a dehydrated file! + /// FIXME: this class is both a remote folder, as the root folder which in turn is the remote FileModifier. + /// This is a mess: unifying remote files/folders is ok, but because it's also the remote root (which + /// should implement the FileModifier), this means that each single remote file/folder also implements + /// this interface. public: static FileInfo A12_B12_C12_S12(); @@ -130,14 +143,14 @@ public: : name { name } { } - FileInfo(const QString &name, qint64 size) + FileInfo(const QString &name, quint64 size) : name { name } , isDir { false } , fileSize(size) , contentSize { size } { } - FileInfo(const QString &name, qint64 size, char contentChar) + FileInfo(const QString &name, quint64 size, char contentChar) : name { name } , isDir { false } , fileSize(size) @@ -151,13 +164,11 @@ public: void remove(const QString &relativePath) override; - void insert(const QString &relativePath, qint64 size = 64, char contentChar = 'W') override; + void insert(const QString &relativePath, quint64 size = DefaultFileSize, char contentChar = DefaultContentChar) override; - void setContents(const QString &relativePath, char contentChar) override; + void setContents(const QString &relativePath, quint64 newSize, char contentChar = DefaultContentChar) override; - void appendByte(const QString &relativePath, char contentChar = 0) override; - - void modifyByte(const QString &relativePath, quint64 offset, char contentChar) override; + void appendByte(const QString &relativePath, char contentChar = DefaultContentChar) override; void mkdir(const QString &relativePath) override; @@ -170,7 +181,7 @@ public: FileInfo *createDir(const QString &relativePath); - FileInfo *create(const QString &relativePath, qint64 size, char contentChar); + FileInfo *create(const QString &relativePath, quint64 size, char contentChar); bool operator<(const FileInfo &other) const { @@ -230,8 +241,8 @@ public: QByteArray fileId = generateFileId(); QByteArray checksums; QByteArray extraDavProperties; - qint64 fileSize = 0; - qint64 contentSize = 0; + quint64 fileSize = 0; + quint64 contentSize = 0; char contentChar = 'W'; bool isDehydratedPlaceholder = false; @@ -259,9 +270,10 @@ public: class FakeReply : public QNetworkReply { Q_OBJECT + public: FakeReply(QObject *parent); - virtual ~FakeReply(); + virtual ~FakeReply() override; // useful to be public for testing using QNetworkReply::setRawHeader; @@ -270,6 +282,7 @@ public: class FakePropfindReply : public FakeReply { Q_OBJECT + public: QByteArray payload; @@ -288,7 +301,6 @@ public: class FakePutReply : public FakeReply { Q_OBJECT - FileInfo *fileInfo; public: FakePutReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, const QByteArray &putPayload, QObject *parent); @@ -299,12 +311,14 @@ public: void abort() override; qint64 readData(char *, qint64) override { return 0; } + +private: + FileInfo *fileInfo; }; class FakeMkcolReply : public FakeReply { Q_OBJECT - FileInfo *fileInfo; public: FakeMkcolReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, QObject *parent); @@ -313,11 +327,15 @@ public: void abort() override { } qint64 readData(char *, qint64) override { return 0; } + +private: + FileInfo *fileInfo; }; class FakeDeleteReply : public FakeReply { Q_OBJECT + public: FakeDeleteReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, QObject *parent); @@ -330,6 +348,7 @@ public: class FakeMoveReply : public FakeReply { Q_OBJECT + public: FakeMoveReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, QObject *parent); @@ -342,6 +361,7 @@ public: class FakeGetReply : public FakeReply { Q_OBJECT + public: enum class State { Ok, @@ -551,7 +571,7 @@ public: FileInfo &remoteModifier() { return _fakeAm->currentRemoteState(); } FileInfo currentLocalState(); - FileInfo currentRemoteState() { return _fakeAm->currentRemoteState(); } + FileInfo ¤tRemoteState() { return _fakeAm->currentRemoteState(); } FileInfo &uploadState() { return _fakeAm->uploadState(); } FileInfo dbState() const; |