зеркало из https://github.com/nextcloud/desktop.git
test that files soon to be expired will be synced automatically
try to ensure that we properly sync again files for which lock has expired Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
This commit is contained in:
Родитель
42f6a63361
Коммит
d371855e56
|
@ -103,6 +103,10 @@ void DiskFileModifier::setModTime(const QString &relativePath, const QDateTime &
|
|||
OCC::FileSystem::setModTime(_rootDir.filePath(relativePath), OCC::Utility::qDateTimeToTime_t(modTime));
|
||||
}
|
||||
|
||||
void DiskFileModifier::modifyLockState([[maybe_unused]] const QString &relativePath, [[maybe_unused]] LockState lockState, [[maybe_unused]] int lockType, [[maybe_unused]] const QString &lockOwner, [[maybe_unused]] const QString &lockOwnerId, [[maybe_unused]] const QString &lockEditorId, [[maybe_unused]] quint64 lockTime, [[maybe_unused]] quint64 lockTimeout)
|
||||
{
|
||||
}
|
||||
|
||||
FileInfo FileInfo::A12_B12_C12_S12()
|
||||
{
|
||||
FileInfo fi { QString {}, {
|
||||
|
@ -195,6 +199,19 @@ void FileInfo::setModTimeKeepEtag(const QString &relativePath, const QDateTime &
|
|||
file->lastModified = modTime;
|
||||
}
|
||||
|
||||
void FileInfo::modifyLockState(const QString &relativePath, LockState lockState, int lockType, const QString &lockOwner, const QString &lockOwnerId, const QString &lockEditorId, quint64 lockTime, quint64 lockTimeout)
|
||||
{
|
||||
FileInfo *file = findInvalidatingEtags(relativePath);
|
||||
Q_ASSERT(file);
|
||||
file->lockState = lockState;
|
||||
file->lockType = lockType;
|
||||
file->lockOwner = lockOwner;
|
||||
file->lockOwnerId = lockOwnerId;
|
||||
file->lockEditorId = lockEditorId;
|
||||
file->lockTime = lockTime;
|
||||
file->lockTimeout = lockTimeout;
|
||||
}
|
||||
|
||||
FileInfo *FileInfo::find(PathComponents pathComponents, const bool invalidateEtags)
|
||||
{
|
||||
if (pathComponents.isEmpty()) {
|
||||
|
@ -334,6 +351,13 @@ FakePropfindReply::FakePropfindReply(FileInfo &remoteRootFileInfo, QNetworkAcces
|
|||
xml.writeTextElement(ocUri, QStringLiteral("permissions"), !fileInfo.permissions.isNull() ? QString(fileInfo.permissions.toString()) : fileInfo.isShared ? QStringLiteral("SRDNVCKW") : QStringLiteral("RDNVCKW"));
|
||||
xml.writeTextElement(ocUri, QStringLiteral("id"), QString::fromUtf8(fileInfo.fileId));
|
||||
xml.writeTextElement(ocUri, QStringLiteral("checksums"), QString::fromUtf8(fileInfo.checksums));
|
||||
xml.writeTextElement(ncUri, QStringLiteral("lock-owner"), fileInfo.lockOwnerId);
|
||||
xml.writeTextElement(ncUri, QStringLiteral("lock"), fileInfo.lockState == FileInfo::LockState::FileLocked ? QStringLiteral("1") : QStringLiteral("0"));
|
||||
xml.writeTextElement(ncUri, QStringLiteral("lock-owner-type"), fileInfo.lockOwnerId);
|
||||
xml.writeTextElement(ncUri, QStringLiteral("lock-owner-displayname"), fileInfo.lockOwnerId);
|
||||
xml.writeTextElement(ncUri, QStringLiteral("lock-owner-editor"), fileInfo.lockOwnerId);
|
||||
xml.writeTextElement(ncUri, QStringLiteral("lock-time"), QString::number(fileInfo.lockTime));
|
||||
xml.writeTextElement(ncUri, QStringLiteral("lock-timeout"), QString::number(fileInfo.lockTimeout));
|
||||
buffer.write(fileInfo.extraDavProperties);
|
||||
xml.writeEndElement(); // prop
|
||||
xml.writeTextElement(davUri, QStringLiteral("status"), QStringLiteral("HTTP/1.1 200 OK"));
|
||||
|
|
|
@ -76,6 +76,11 @@ public:
|
|||
class FileModifier
|
||||
{
|
||||
public:
|
||||
enum class LockState {
|
||||
FileLocked,
|
||||
FileUnlocked,
|
||||
};
|
||||
|
||||
virtual ~FileModifier() = default;
|
||||
virtual void remove(const QString &relativePath) = 0;
|
||||
virtual void insert(const QString &relativePath, qint64 size = 64, char contentChar = 'W') = 0;
|
||||
|
@ -84,6 +89,7 @@ public:
|
|||
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;
|
||||
virtual void modifyLockState(const QString &relativePath, LockState lockState, int lockType, const QString &lockOwner, const QString &lockOwnerId, const QString &lockEditorId, quint64 lockTime, quint64 lockTimeout) = 0;
|
||||
};
|
||||
|
||||
class DiskFileModifier : public FileModifier
|
||||
|
@ -99,6 +105,7 @@ public:
|
|||
void mkdir(const QString &relativePath) override;
|
||||
void rename(const QString &from, const QString &to) override;
|
||||
void setModTime(const QString &relativePath, const QDateTime &modTime) override;
|
||||
void modifyLockState(const QString &relativePath, LockState lockState, int lockType, const QString &lockOwner, const QString &lockOwnerId, const QString &lockEditorId, quint64 lockTime, quint64 lockTimeout) override;
|
||||
};
|
||||
|
||||
class FileInfo : public FileModifier
|
||||
|
@ -130,6 +137,8 @@ public:
|
|||
|
||||
void setModTimeKeepEtag(const QString &relativePath, const QDateTime &modTime);
|
||||
|
||||
void modifyLockState(const QString &relativePath, LockState lockState, int lockType, const QString &lockOwner, const QString &lockOwnerId, const QString &lockEditorId, quint64 lockTime, quint64 lockTimeout) override;
|
||||
|
||||
FileInfo *find(PathComponents pathComponents, const bool invalidateEtags = false);
|
||||
|
||||
FileInfo *createDir(const QString &relativePath);
|
||||
|
@ -163,6 +172,13 @@ public:
|
|||
QByteArray extraDavProperties;
|
||||
qint64 size = 0;
|
||||
char contentChar = 'W';
|
||||
LockState lockState = LockState::FileUnlocked;
|
||||
int lockType = 0;
|
||||
QString lockOwner;
|
||||
QString lockOwnerId;
|
||||
QString lockEditorId;
|
||||
quint64 lockTime = 0;
|
||||
quint64 lockTimeout = 0;
|
||||
|
||||
// Sorted by name to be able to compare trees
|
||||
QMap<QString, FileInfo> children;
|
||||
|
|
|
@ -621,15 +621,7 @@ private slots:
|
|||
|
||||
fakeFolder.remoteModifier().insert(fooFileRootFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileRootFolder);
|
||||
|
||||
const auto lockedFileDavProps = QByteArray("<nc:lock>1</nc:lock>"
|
||||
"<nc:lock-owner-type>0</nc:lock-owner-type>"
|
||||
"<nc:lock-owner>user1</nc:lock-owner>"
|
||||
"<nc:lock-owner-displayname>user1</nc:lock-owner-displayname>"
|
||||
"<nc:lock-owner-editor>user1</nc:lock-owner-editor>"
|
||||
"<nc:lock-time>1648046707</nc:lock-time>");
|
||||
|
||||
fakeFolder.remoteModifier().find("bar")->extraDavProperties = lockedFileDavProps;
|
||||
fakeFolder.remoteModifier().modifyLockState(QStringLiteral("bar"), FileInfo::LockState::FileLocked, 0, QStringLiteral("user1"), {}, QStringLiteral("user1"), 1648046707, 0);
|
||||
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileSubFolder);
|
||||
|
@ -648,8 +640,7 @@ private slots:
|
|||
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("bar"), &fileRecordBefore));
|
||||
QVERIFY(fileRecordBefore._lockstate._locked);
|
||||
|
||||
const auto unlockedFileDavProps = QByteArray("<nc:lock>0</nc:lock>");
|
||||
fakeFolder.remoteModifier().find("bar")->extraDavProperties = unlockedFileDavProps;
|
||||
fakeFolder.remoteModifier().modifyLockState(QStringLiteral("bar"), FileInfo::LockState::FileUnlocked, {}, {}, {}, {}, {}, {});
|
||||
|
||||
fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "common/syncjournaldb.h"
|
||||
#include "common/syncjournalfilerecord.h"
|
||||
#include "syncenginetestutils.h"
|
||||
#include "localdiscoverytracker.h"
|
||||
|
||||
#include <QTest>
|
||||
#include <QSignalSpy>
|
||||
|
@ -482,6 +483,93 @@ private slots:
|
|||
QVERIFY(jobFailure.wait());
|
||||
QCOMPARE(jobSuccess.count(), 0);
|
||||
}
|
||||
|
||||
void testSyncLockedFilesAlmostExpired()
|
||||
{
|
||||
FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
|
||||
QSignalSpy spySyncCompleted(&fakeFolder.syncEngine(), &OCC::SyncEngine::finished);
|
||||
|
||||
ItemCompletedSpy completeSpy(fakeFolder);
|
||||
|
||||
completeSpy.clear();
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
QCOMPARE(completeSpy.findItem(QStringLiteral("A/a1"))->_locked, OCC::SyncFileItem::LockStatus::UnlockedItem);
|
||||
OCC::SyncJournalFileRecord fileRecordBefore;
|
||||
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1"), &fileRecordBefore));
|
||||
QVERIFY(!fileRecordBefore._lockstate._locked);
|
||||
|
||||
fakeFolder.remoteModifier().modifyLockState(QStringLiteral("A/a1"), FileModifier::LockState::FileLocked, 1, QStringLiteral("Nextcloud Office"), {}, QStringLiteral("richdocuments"), QDateTime::currentDateTime().toSecsSinceEpoch() - 1220, 1226);
|
||||
|
||||
completeSpy.clear();
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
QCOMPARE(completeSpy.findItem(QStringLiteral("A/a1"))->_locked, OCC::SyncFileItem::LockStatus::LockedItem);
|
||||
OCC::SyncJournalFileRecord fileRecordLocked;
|
||||
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1"), &fileRecordLocked));
|
||||
QVERIFY(fileRecordLocked._lockstate._locked);
|
||||
|
||||
spySyncCompleted.clear();
|
||||
|
||||
QTest::qWait(5000);
|
||||
|
||||
fakeFolder.remoteModifier().modifyLockState(QStringLiteral("A/a1"), FileModifier::LockState::FileUnlocked, {}, {}, {}, {}, {}, {});
|
||||
|
||||
QCOMPARE(spySyncCompleted.count(), 0);
|
||||
QVERIFY(spySyncCompleted.wait(3000));
|
||||
QCOMPARE(spySyncCompleted.count(), 1);
|
||||
|
||||
OCC::SyncJournalFileRecord fileRecordUnlocked;
|
||||
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1"), &fileRecordUnlocked));
|
||||
QVERIFY(!fileRecordUnlocked._lockstate._locked);
|
||||
}
|
||||
|
||||
void testSyncLockedFilesNoExpiredLockedFiles()
|
||||
{
|
||||
FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
|
||||
QSignalSpy spySyncCompleted(&fakeFolder.syncEngine(), &OCC::SyncEngine::finished);
|
||||
|
||||
ItemCompletedSpy completeSpy(fakeFolder);
|
||||
|
||||
completeSpy.clear();
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
QCOMPARE(completeSpy.findItem(QStringLiteral("A/a1"))->_locked, OCC::SyncFileItem::LockStatus::UnlockedItem);
|
||||
OCC::SyncJournalFileRecord fileRecordBefore;
|
||||
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1"), &fileRecordBefore));
|
||||
QVERIFY(!fileRecordBefore._lockstate._locked);
|
||||
|
||||
fakeFolder.remoteModifier().modifyLockState(QStringLiteral("A/a1"), FileModifier::LockState::FileLocked, 1, QStringLiteral("Nextcloud Office"), {}, QStringLiteral("richdocuments"), QDateTime::currentDateTime().toSecsSinceEpoch() - 1220, 1226);
|
||||
|
||||
completeSpy.clear();
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
QCOMPARE(completeSpy.findItem(QStringLiteral("A/a1"))->_locked, OCC::SyncFileItem::LockStatus::LockedItem);
|
||||
OCC::SyncJournalFileRecord fileRecordLocked;
|
||||
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1"), &fileRecordLocked));
|
||||
QVERIFY(fileRecordLocked._lockstate._locked);
|
||||
|
||||
completeSpy.clear();
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
spySyncCompleted.clear();
|
||||
|
||||
QTest::qWait(1000);
|
||||
|
||||
fakeFolder.remoteModifier().modifyLockState(QStringLiteral("A/a1"), FileModifier::LockState::FileUnlocked, {}, {}, {}, {}, {}, {});
|
||||
|
||||
QCOMPARE(spySyncCompleted.count(), 0);
|
||||
QVERIFY(!spySyncCompleted.wait(3000));
|
||||
QCOMPARE(spySyncCompleted.count(), 0);
|
||||
|
||||
OCC::SyncJournalFileRecord fileRecordUnlocked;
|
||||
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1"), &fileRecordUnlocked));
|
||||
QVERIFY(fileRecordUnlocked._lockstate._locked);
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_GUILESS_MAIN(TestLockFile)
|
||||
|
|
Загрузка…
Ссылка в новой задаче