mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-29 12:19:03 +03:00
Merge pull request #4319 from nextcloud/bugfix/preventOverflowWithMtime
Bugfix/prevent overflow with mtime
This commit is contained in:
commit
e72d59c4ff
13 changed files with 504 additions and 36 deletions
|
@ -436,7 +436,7 @@ QString UserStatusSelectorModel::clearAtReadable(const Optional<ClearAt> &clearA
|
|||
}
|
||||
|
||||
case ClearAtType::Timestamp: {
|
||||
const int difference = static_cast<int>(clearAt->_timestamp - _dateTimeProvider->currentDateTime().toTime_t());
|
||||
const int difference = static_cast<int>(clearAt->_timestamp - _dateTimeProvider->currentDateTime().toSecsSinceEpoch());
|
||||
return timeDifferenceToString(difference);
|
||||
}
|
||||
|
||||
|
|
|
@ -539,19 +539,11 @@ void ProcessDirectoryJob::processFileAnalyzeRemoteInfo(
|
|||
} else {
|
||||
item->_instruction = CSYNC_INSTRUCTION_SYNC;
|
||||
}
|
||||
} else if (dbEntry._modtime <= 0 && serverEntry.modtime > 0) {
|
||||
} else if (dbEntry._modtime != serverEntry.modtime && localEntry.size == serverEntry.size && dbEntry._fileSize == serverEntry.size && dbEntry._etag == serverEntry.etag) {
|
||||
item->_direction = SyncFileItem::Down;
|
||||
item->_modtime = serverEntry.modtime;
|
||||
item->_size = sizeOnServer;
|
||||
if (serverEntry.isDirectory) {
|
||||
ENFORCE(dbEntry.isDirectory());
|
||||
item->_instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
} else if (!localEntry.isValid() && _queryLocal != ParentNotChanged) {
|
||||
// Deleted locally, changed on server
|
||||
item->_instruction = CSYNC_INSTRUCTION_NEW;
|
||||
} else {
|
||||
item->_instruction = CSYNC_INSTRUCTION_SYNC;
|
||||
}
|
||||
} else if (dbEntry._remotePerm != serverEntry.remotePerm || dbEntry._fileId != serverEntry.fileId || metaDataSizeNeedsUpdateForE2EeFilePlaceholder) {
|
||||
if (metaDataSizeNeedsUpdateForE2EeFilePlaceholder) {
|
||||
// we are updating placeholder sizes after migrating from older versions with VFS + E2EE implicit hydration not supported
|
||||
|
@ -848,6 +840,13 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo(
|
|||
if (_queryLocal != NormalQuery && _queryServer != NormalQuery)
|
||||
recurse = false;
|
||||
|
||||
if ((item->_direction == SyncFileItem::Down || item->_instruction == CSYNC_INSTRUCTION_CONFLICT || item->_instruction == CSYNC_INSTRUCTION_NEW || item->_instruction == CSYNC_INSTRUCTION_SYNC) &&
|
||||
(item->_modtime <= 0 || item->_modtime >= 0xFFFFFFFF)) {
|
||||
item->_instruction = CSYNC_INSTRUCTION_ERROR;
|
||||
item->_errorString = tr("Cannot sync due to invalid modification time");
|
||||
item->_status = SyncFileItem::Status::NormalError;
|
||||
}
|
||||
|
||||
auto recurseQueryLocal = _queryLocal == ParentNotChanged ? ParentNotChanged : localEntry.isDirectory || item->_instruction == CSYNC_INSTRUCTION_RENAME ? NormalQuery : ParentDontExist;
|
||||
processFileFinalize(item, path, recurse, recurseQueryLocal, recurseQueryServer);
|
||||
};
|
||||
|
@ -875,14 +874,14 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo(
|
|||
}
|
||||
path._original = originalPath;
|
||||
item->_originalFile = path._original;
|
||||
item->_modtime = base._modtime;
|
||||
item->_inode = base._inode;
|
||||
item->_modtime = base.isValid() ? base._modtime : localEntry.modtime;
|
||||
item->_inode = base.isValid() ? base._inode : localEntry.inode;
|
||||
item->_instruction = CSYNC_INSTRUCTION_RENAME;
|
||||
item->_direction = direction;
|
||||
item->_fileId = base._fileId;
|
||||
item->_remotePerm = base._remotePerm;
|
||||
item->_etag = base._etag;
|
||||
item->_type = base._type;
|
||||
item->_fileId = base.isValid() ? base._fileId : QByteArray{};
|
||||
item->_remotePerm = base.isValid() ? base._remotePerm : RemotePermissions{};
|
||||
item->_etag = base.isValid() ? base._etag : QByteArray{};
|
||||
item->_type = base.isValid() ? base._type : localEntry.type;
|
||||
};
|
||||
|
||||
if (!localEntry.isValid()) {
|
||||
|
@ -1001,8 +1000,8 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo(
|
|||
item->_modtime = localEntry.modtime;
|
||||
item->_type = localEntry.isDirectory ? ItemTypeDirectory : ItemTypeFile;
|
||||
_childModified = true;
|
||||
} else if (dbEntry._modtime > 0 && localEntry.modtime <= 0) {
|
||||
item->_instruction = CSYNC_INSTRUCTION_SYNC;
|
||||
} else if (dbEntry._modtime > 0 && (localEntry.modtime <= 0 || localEntry.modtime >= 0xFFFFFFFF) && dbEntry._fileSize == localEntry.size) {
|
||||
item->_instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
item->_direction = SyncFileItem::Down;
|
||||
item->_size = localEntry.size > 0 ? localEntry.size : dbEntry._fileSize;
|
||||
item->_modtime = dbEntry._modtime;
|
||||
|
|
|
@ -407,7 +407,10 @@ static void propertyMapToRemoteInfo(const QMap<QString, QString> &map, RemoteInf
|
|||
} else if (property == QLatin1String("getlastmodified")) {
|
||||
const auto date = QDateTime::fromString(value, Qt::RFC2822Date);
|
||||
Q_ASSERT(date.isValid());
|
||||
result.modtime = date.toTime_t();
|
||||
result.modtime = 0;
|
||||
if (date.toSecsSinceEpoch() > 0) {
|
||||
result.modtime = date.toSecsSinceEpoch();
|
||||
}
|
||||
} else if (property == QLatin1String("getcontentlength")) {
|
||||
// See #4573, sometimes negative size values are returned
|
||||
bool ok = false;
|
||||
|
|
|
@ -110,18 +110,18 @@ quint64 clearAtEndOfToTimestamp(const OCC::ClearAt &clearAt)
|
|||
Q_ASSERT(clearAt._type == OCC::ClearAtType::EndOf);
|
||||
|
||||
if (clearAt._endof == "day") {
|
||||
return QDate::currentDate().addDays(1).startOfDay().toTime_t();
|
||||
return QDate::currentDate().addDays(1).startOfDay().toSecsSinceEpoch();
|
||||
} else if (clearAt._endof == "week") {
|
||||
const auto days = Qt::Sunday - QDate::currentDate().dayOfWeek();
|
||||
return QDate::currentDate().addDays(days + 1).startOfDay().toTime_t();
|
||||
return QDate::currentDate().addDays(days + 1).startOfDay().toSecsSinceEpoch();
|
||||
}
|
||||
qCWarning(lcOcsUserStatusConnector) << "Can not handle clear at endof day type" << clearAt._endof;
|
||||
return QDateTime::currentDateTime().toTime_t();
|
||||
return QDateTime::currentDateTime().toSecsSinceEpoch();
|
||||
}
|
||||
|
||||
quint64 clearAtPeriodToTimestamp(const OCC::ClearAt &clearAt)
|
||||
{
|
||||
return QDateTime::currentDateTime().addSecs(clearAt._period).toTime_t();
|
||||
return QDateTime::currentDateTime().addSecs(clearAt._period).toSecsSinceEpoch();
|
||||
}
|
||||
|
||||
quint64 clearAtToTimestamp(const OCC::ClearAt &clearAt)
|
||||
|
|
|
@ -563,7 +563,6 @@ void PropagateDownloadFile::startAfterIsEncryptedIsChecked()
|
|||
return checksum_header.startsWith("SHA")
|
||||
|| checksum_header.startsWith("MD5:");
|
||||
};
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateDownload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
|
|
|
@ -353,8 +353,10 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
|
|||
if (item->_type == ItemTypeFile) {
|
||||
const auto result = _syncOptions._vfs->convertToPlaceholder(filePath, *item);
|
||||
if (!result) {
|
||||
item->_status = SyncFileItem::Status::NormalError;
|
||||
item->_instruction = CSYNC_INSTRUCTION_ERROR;
|
||||
item->_errorString = tr("Could not update file: %1").arg(result.error());
|
||||
emit itemCompleted(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -363,8 +365,10 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
|
|||
if (item->_type == ItemTypeVirtualFile) {
|
||||
auto r = _syncOptions._vfs->updateMetadata(filePath, item->_modtime, item->_size, item->_fileId);
|
||||
if (!r) {
|
||||
item->_status = SyncFileItem::Status::NormalError;
|
||||
item->_instruction = CSYNC_INSTRUCTION_ERROR;
|
||||
item->_errorString = tr("Could not update virtual file metadata: %1").arg(r.error());
|
||||
emit itemCompleted(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,6 +188,13 @@ void FileInfo::setModTime(const QString &relativePath, const QDateTime &modTime)
|
|||
file->lastModified = modTime;
|
||||
}
|
||||
|
||||
void FileInfo::setModTimeKeepEtag(const QString &relativePath, const QDateTime &modTime)
|
||||
{
|
||||
FileInfo *file = find(relativePath);
|
||||
Q_ASSERT(file);
|
||||
file->lastModified = modTime;
|
||||
}
|
||||
|
||||
FileInfo *FileInfo::find(PathComponents pathComponents, const bool invalidateEtags)
|
||||
{
|
||||
if (pathComponents.isEmpty()) {
|
||||
|
|
|
@ -128,6 +128,8 @@ public:
|
|||
|
||||
void setModTime(const QString &relativePath, const QDateTime &modTime) override;
|
||||
|
||||
void setModTimeKeepEtag(const QString &relativePath, const QDateTime &modTime);
|
||||
|
||||
FileInfo *find(PathComponents pathComponents, const bool invalidateEtags = false);
|
||||
|
||||
FileInfo *createDir(const QString &relativePath);
|
||||
|
|
|
@ -386,6 +386,204 @@ private slots:
|
|||
qDebug() << expectedState;
|
||||
QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
|
||||
}
|
||||
|
||||
void testBlockInvalidMtimeSyncRemote()
|
||||
{
|
||||
constexpr auto INVALID_MODTIME1 = 0;
|
||||
constexpr auto INVALID_MODTIME2 = -3600;
|
||||
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
const QString fooFileRootFolder("foo");
|
||||
const QString barFileRootFolder("bar");
|
||||
const QString blaFileRootFolder("bla");
|
||||
const QString fooFileSubFolder("subfolder/foo");
|
||||
const QString barFileSubFolder("subfolder/bar");
|
||||
const QString blaFileSubFolder("subfolder/bla");
|
||||
|
||||
fakeFolder.remoteModifier().insert(fooFileRootFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileRootFolder);
|
||||
fakeFolder.remoteModifier().insert(blaFileRootFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileSubFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileSubFolder);
|
||||
fakeFolder.remoteModifier().insert(blaFileSubFolder);
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
fakeFolder.remoteModifier().setModTime(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
fakeFolder.remoteModifier().setModTime(barFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
fakeFolder.remoteModifier().setModTime(blaFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
fakeFolder.remoteModifier().setModTime(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
fakeFolder.remoteModifier().setModTime(barFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
fakeFolder.remoteModifier().setModTime(blaFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
|
||||
fakeFolder.remoteModifier().setModTime(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
fakeFolder.remoteModifier().setModTime(barFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
fakeFolder.remoteModifier().setModTime(blaFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
fakeFolder.remoteModifier().setModTime(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
fakeFolder.remoteModifier().setModTime(barFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
fakeFolder.remoteModifier().setModTime(blaFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
}
|
||||
|
||||
void testBlockInvalidMtimeSyncLocal()
|
||||
{
|
||||
constexpr auto INVALID_MODTIME1 = 0;
|
||||
constexpr auto INVALID_MODTIME2 = -3600;
|
||||
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
|
||||
int nGET = 0;
|
||||
fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &, QIODevice *) {
|
||||
if (op == QNetworkAccessManager::GetOperation)
|
||||
++nGET;
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
const QString fooFileRootFolder("foo");
|
||||
const QString barFileRootFolder("bar");
|
||||
const QString blaFileRootFolder("bla");
|
||||
const QString fooFileSubFolder("subfolder/foo");
|
||||
const QString barFileSubFolder("subfolder/bar");
|
||||
const QString blaFileSubFolder("subfolder/bla");
|
||||
|
||||
fakeFolder.remoteModifier().insert(fooFileRootFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileRootFolder);
|
||||
fakeFolder.remoteModifier().insert(blaFileRootFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileSubFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileSubFolder);
|
||||
fakeFolder.remoteModifier().insert(blaFileSubFolder);
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
nGET = 0;
|
||||
|
||||
fakeFolder.localModifier().setModTime(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
fakeFolder.localModifier().setModTime(barFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
fakeFolder.localModifier().setModTime(blaFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
fakeFolder.localModifier().setModTime(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
fakeFolder.localModifier().setModTime(barFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
fakeFolder.localModifier().setModTime(blaFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME1));
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
QCOMPARE(nGET, 0);
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
QCOMPARE(nGET, 0);
|
||||
|
||||
fakeFolder.localModifier().setModTime(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
fakeFolder.localModifier().setModTime(barFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
fakeFolder.localModifier().setModTime(blaFileRootFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
fakeFolder.localModifier().setModTime(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
fakeFolder.localModifier().setModTime(barFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
fakeFolder.localModifier().setModTime(blaFileSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MODTIME2));
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
QCOMPARE(nGET, 0);
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
QCOMPARE(nGET, 0);
|
||||
}
|
||||
|
||||
void testDoNotSyncInvalidFutureMtime()
|
||||
{
|
||||
constexpr auto FUTURE_MTIME = 0xFFFFFFFF;
|
||||
constexpr auto CURRENT_MTIME = 1646057277;
|
||||
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
|
||||
const QString fooFileRootFolder("foo");
|
||||
const QString barFileRootFolder("bar");
|
||||
const QString fooFileSubFolder("subfolder/foo");
|
||||
const QString barFileSubFolder("subfolder/bar");
|
||||
const QString fooFileAaaSubFolder("aaa/subfolder/foo");
|
||||
const QString barFileAaaSubFolder("aaa/subfolder/bar");
|
||||
|
||||
fakeFolder.remoteModifier().insert(fooFileRootFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileRootFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileSubFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileSubFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa"));
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa/subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileAaaSubFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileAaaSubFolder);
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
fakeFolder.remoteModifier().setModTime(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.remoteModifier().setModTime(barFileRootFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.remoteModifier().setModTime(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.remoteModifier().setModTime(barFileSubFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.remoteModifier().setModTime(fooFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.remoteModifier().setModTime(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.localModifier().setModTime(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.localModifier().setModTime(barFileRootFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.localModifier().setModTime(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.localModifier().setModTime(barFileSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.localModifier().setModTime(fooFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.localModifier().setModTime(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
}
|
||||
|
||||
void testInvalidFutureMtimeRecovery()
|
||||
{
|
||||
constexpr auto FUTURE_MTIME = 0xFFFFFFFF;
|
||||
constexpr auto CURRENT_MTIME = 1646057277;
|
||||
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
|
||||
const QString fooFileRootFolder("foo");
|
||||
const QString barFileRootFolder("bar");
|
||||
const QString fooFileSubFolder("subfolder/foo");
|
||||
const QString barFileSubFolder("subfolder/bar");
|
||||
const QString fooFileAaaSubFolder("aaa/subfolder/foo");
|
||||
const QString barFileAaaSubFolder("aaa/subfolder/bar");
|
||||
|
||||
fakeFolder.remoteModifier().insert(fooFileRootFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileRootFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileSubFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileSubFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa"));
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa/subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileAaaSubFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileAaaSubFolder);
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(barFileRootFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(barFileSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(fooFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.localModifier().setModTime(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.localModifier().setModTime(barFileRootFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.localModifier().setModTime(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.localModifier().setModTime(barFileSubFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.localModifier().setModTime(fooFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.localModifier().setModTime(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
auto expectedState = fakeFolder.currentLocalState();
|
||||
QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_GUILESS_MAIN(TestLocalDiscovery)
|
||||
|
|
|
@ -158,7 +158,7 @@ createFakePredefinedStatuses(const QDateTime ¤tTime)
|
|||
OCC::Optional<OCC::ClearAt> userStatusClearAt;
|
||||
OCC::ClearAt clearAt;
|
||||
clearAt._type = OCC::ClearAtType::Timestamp;
|
||||
clearAt._timestamp = currentTime.addSecs(60 * 60).toTime_t();
|
||||
clearAt._timestamp = currentTime.addSecs(60 * 60).toSecsSinceEpoch();
|
||||
userStatusClearAt = clearAt;
|
||||
|
||||
statuses.emplace_back(userStatusId, userStatusMessage, userStatusIcon,
|
||||
|
@ -198,7 +198,7 @@ private slots:
|
|||
{
|
||||
OCC::ClearAt clearAt;
|
||||
clearAt._type = OCC::ClearAtType::Timestamp;
|
||||
clearAt._timestamp = currentDateTime.addDays(1).toTime_t();
|
||||
clearAt._timestamp = currentDateTime.addDays(1).toSecsSinceEpoch();
|
||||
userStatusClearAt = clearAt;
|
||||
}
|
||||
|
||||
|
@ -488,7 +488,7 @@ private slots:
|
|||
OCC::UserStatus userStatus;
|
||||
OCC::ClearAt clearAt;
|
||||
clearAt._type = OCC::ClearAtType::Timestamp;
|
||||
clearAt._timestamp = currentTime.addSecs(30).toTime_t();
|
||||
clearAt._timestamp = currentTime.addSecs(30).toSecsSinceEpoch();
|
||||
userStatus.setClearAt(clearAt);
|
||||
|
||||
auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
|
||||
|
@ -503,7 +503,7 @@ private slots:
|
|||
OCC::UserStatus userStatus;
|
||||
OCC::ClearAt clearAt;
|
||||
clearAt._type = OCC::ClearAtType::Timestamp;
|
||||
clearAt._timestamp = currentTime.addSecs(60).toTime_t();
|
||||
clearAt._timestamp = currentTime.addSecs(60).toSecsSinceEpoch();
|
||||
userStatus.setClearAt(clearAt);
|
||||
|
||||
auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
|
||||
|
@ -518,7 +518,7 @@ private slots:
|
|||
OCC::UserStatus userStatus;
|
||||
OCC::ClearAt clearAt;
|
||||
clearAt._type = OCC::ClearAtType::Timestamp;
|
||||
clearAt._timestamp = currentTime.addSecs(60 * 30).toTime_t();
|
||||
clearAt._timestamp = currentTime.addSecs(60 * 30).toSecsSinceEpoch();
|
||||
userStatus.setClearAt(clearAt);
|
||||
|
||||
auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
|
||||
|
@ -533,7 +533,7 @@ private slots:
|
|||
OCC::UserStatus userStatus;
|
||||
OCC::ClearAt clearAt;
|
||||
clearAt._type = OCC::ClearAtType::Timestamp;
|
||||
clearAt._timestamp = currentTime.addSecs(60 * 60).toTime_t();
|
||||
clearAt._timestamp = currentTime.addSecs(60 * 60).toSecsSinceEpoch();
|
||||
userStatus.setClearAt(clearAt);
|
||||
|
||||
auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
|
||||
|
@ -548,7 +548,7 @@ private slots:
|
|||
OCC::UserStatus userStatus;
|
||||
OCC::ClearAt clearAt;
|
||||
clearAt._type = OCC::ClearAtType::Timestamp;
|
||||
clearAt._timestamp = currentTime.addSecs(60 * 60 * 4).toTime_t();
|
||||
clearAt._timestamp = currentTime.addSecs(60 * 60 * 4).toSecsSinceEpoch();
|
||||
userStatus.setClearAt(clearAt);
|
||||
|
||||
auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
|
||||
|
@ -563,7 +563,7 @@ private slots:
|
|||
OCC::UserStatus userStatus;
|
||||
OCC::ClearAt clearAt;
|
||||
clearAt._type = OCC::ClearAtType::Timestamp;
|
||||
clearAt._timestamp = currentTime.addDays(1).toTime_t();
|
||||
clearAt._timestamp = currentTime.addDays(1).toSecsSinceEpoch();
|
||||
userStatus.setClearAt(clearAt);
|
||||
|
||||
auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
|
||||
|
@ -578,7 +578,7 @@ private slots:
|
|||
OCC::UserStatus userStatus;
|
||||
OCC::ClearAt clearAt;
|
||||
clearAt._type = OCC::ClearAtType::Timestamp;
|
||||
clearAt._timestamp = currentTime.addDays(7).toTime_t();
|
||||
clearAt._timestamp = currentTime.addDays(7).toSecsSinceEpoch();
|
||||
userStatus.setClearAt(clearAt);
|
||||
|
||||
auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
|
||||
|
|
|
@ -1129,6 +1129,121 @@ private slots:
|
|||
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
}
|
||||
|
||||
void testFolderWithFilesInError()
|
||||
{
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
|
||||
fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData) -> QNetworkReply * {
|
||||
Q_UNUSED(outgoingData)
|
||||
|
||||
if (op == QNetworkAccessManager::GetOperation) {
|
||||
const auto fileName = getFilePathFromUrl(request.url());
|
||||
if (fileName == QStringLiteral("aaa/subfolder/foo")) {
|
||||
return new FakeErrorReply(op, request, &fakeFolder.syncEngine(), 403);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa"));
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa/subfolder"));
|
||||
fakeFolder.remoteModifier().insert(QStringLiteral("aaa/subfolder/bar"));
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
fakeFolder.remoteModifier().insert(QStringLiteral("aaa/subfolder/foo"));
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
}
|
||||
|
||||
void testInvalidMtimeRecoveryAtStart()
|
||||
{
|
||||
constexpr auto INVALID_MTIME = 0;
|
||||
constexpr auto CURRENT_MTIME = 1646057277;
|
||||
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
|
||||
const QString fooFileRootFolder("foo");
|
||||
const QString barFileRootFolder("bar");
|
||||
const QString fooFileSubFolder("subfolder/foo");
|
||||
const QString barFileSubFolder("subfolder/bar");
|
||||
const QString fooFileAaaSubFolder("aaa/subfolder/foo");
|
||||
const QString barFileAaaSubFolder("aaa/subfolder/bar");
|
||||
|
||||
fakeFolder.remoteModifier().insert(fooFileRootFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileRootFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileSubFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileSubFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa"));
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa/subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileAaaSubFolder);
|
||||
fakeFolder.remoteModifier().setModTime(fooFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MTIME));
|
||||
fakeFolder.remoteModifier().insert(barFileAaaSubFolder);
|
||||
fakeFolder.remoteModifier().setModTime(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MTIME));
|
||||
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(fooFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
auto expectedState = fakeFolder.currentLocalState();
|
||||
QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
|
||||
}
|
||||
|
||||
void testInvalidMtimeRecovery()
|
||||
{
|
||||
constexpr auto INVALID_MTIME = 0;
|
||||
constexpr auto CURRENT_MTIME = 1646057277;
|
||||
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
|
||||
const QString fooFileRootFolder("foo");
|
||||
const QString barFileRootFolder("bar");
|
||||
const QString fooFileSubFolder("subfolder/foo");
|
||||
const QString barFileSubFolder("subfolder/bar");
|
||||
const QString fooFileAaaSubFolder("aaa/subfolder/foo");
|
||||
const QString barFileAaaSubFolder("aaa/subfolder/bar");
|
||||
|
||||
fakeFolder.remoteModifier().insert(fooFileRootFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileRootFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileSubFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileSubFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa"));
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa/subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileAaaSubFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileAaaSubFolder);
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
fakeFolder.remoteModifier().setModTime(fooFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MTIME));
|
||||
fakeFolder.remoteModifier().setModTime(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MTIME));
|
||||
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(fooFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
auto expectedState = fakeFolder.currentLocalState();
|
||||
QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_GUILESS_MAIN(TestSyncEngine)
|
||||
|
|
|
@ -107,8 +107,6 @@ private slots:
|
|||
QVERIFY(storedRecord._remotePerm == record._remotePerm);
|
||||
QVERIFY(storedRecord._checksumHeader == record._checksumHeader);
|
||||
|
||||
// qDebug()<< "OOOOO " << storedRecord._modtime.toTime_t() << record._modtime.toTime_t();
|
||||
|
||||
// Attention: compare time_t types here, as QDateTime seem to maintain
|
||||
// milliseconds internally, which disappear in sqlite. Go for full seconds here.
|
||||
QVERIFY(storedRecord._modtime == record._modtime);
|
||||
|
|
|
@ -1517,6 +1517,149 @@ private slots:
|
|||
QCOMPARE(fakeFolder.currentLocalState().find("A/hello" DVSUFFIX)->size, 222);
|
||||
QCOMPARE(fakeFolder.currentLocalState().find("A/igno" DVSUFFIX)->size, 123);
|
||||
}
|
||||
|
||||
void testUpdateMetadataErrorManagement()
|
||||
{
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
setupVfs(fakeFolder);
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
|
||||
// Existing files are propagated just fine in both directions
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa"));
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa/subfolder"));
|
||||
fakeFolder.remoteModifier().insert(QStringLiteral("aaa/subfolder/bar"));
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
// New files on the remote create virtual files
|
||||
fakeFolder.remoteModifier().setModTime(QStringLiteral("aaa/subfolder/bar"), QDateTime::fromSecsSinceEpoch(0));
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(!fakeFolder.syncOnce());
|
||||
}
|
||||
|
||||
void testInvalidFutureMtimeRecovery()
|
||||
{
|
||||
constexpr auto FUTURE_MTIME = 0xFFFFFFFF;
|
||||
constexpr auto CURRENT_MTIME = 1646057277;
|
||||
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
setupVfs(fakeFolder);
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
|
||||
const QString fooFileRootFolder("foo");
|
||||
const QString barFileRootFolder("bar");
|
||||
const QString fooFileSubFolder("subfolder/foo");
|
||||
const QString barFileSubFolder("subfolder/bar");
|
||||
const QString fooFileAaaSubFolder("aaa/subfolder/foo");
|
||||
const QString barFileAaaSubFolder("aaa/subfolder/bar");
|
||||
|
||||
fakeFolder.remoteModifier().insert(fooFileRootFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileRootFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileSubFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileSubFolder);
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa"));
|
||||
fakeFolder.remoteModifier().mkdir(QStringLiteral("aaa/subfolder"));
|
||||
fakeFolder.remoteModifier().insert(fooFileAaaSubFolder);
|
||||
fakeFolder.remoteModifier().insert(barFileAaaSubFolder);
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(barFileRootFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(barFileSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(fooFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.remoteModifier().setModTimeKeepEtag(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
fakeFolder.localModifier().setModTime(fooFileRootFolder + DVSUFFIX, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.localModifier().setModTime(barFileRootFolder + DVSUFFIX, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.localModifier().setModTime(fooFileSubFolder + DVSUFFIX, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.localModifier().setModTime(barFileSubFolder + DVSUFFIX, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.localModifier().setModTime(fooFileAaaSubFolder + DVSUFFIX, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
fakeFolder.localModifier().setModTime(barFileAaaSubFolder + DVSUFFIX, QDateTime::fromSecsSinceEpoch(FUTURE_MTIME));
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
}
|
||||
|
||||
void testInvalidMtimeLocalDiscovery()
|
||||
{
|
||||
constexpr auto INVALID_MTIME1 = 0;
|
||||
constexpr auto INVALID_MTIME2 = 0xFFFFFFFF;
|
||||
constexpr auto CURRENT_MTIME = 1646057277;
|
||||
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
setupVfs(fakeFolder);
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
QSignalSpy statusSpy(&fakeFolder.syncEngine().syncFileStatusTracker(), &SyncFileStatusTracker::fileStatusChanged);
|
||||
|
||||
const QString fooFileRootFolder("foo");
|
||||
const QString barFileRootFolder("bar");
|
||||
const QString fooFileSubFolder("subfolder/foo");
|
||||
const QString barFileSubFolder("subfolder/bar");
|
||||
const QString fooFileAaaSubFolder("aaa/subfolder/foo");
|
||||
const QString barFileAaaSubFolder("aaa/subfolder/bar");
|
||||
|
||||
auto checkStatus = [&]() -> SyncFileStatus::SyncFileStatusTag {
|
||||
auto file = QFileInfo{fakeFolder.syncEngine().localPath(), barFileAaaSubFolder};
|
||||
auto locPath = fakeFolder.syncEngine().localPath();
|
||||
auto itemFound = false;
|
||||
// Start from the end to get the latest status
|
||||
for (int i = statusSpy.size() - 1; i >= 0 && !itemFound; --i) {
|
||||
if (QFileInfo(statusSpy.at(i)[0].toString()) == file) {
|
||||
itemFound = true;
|
||||
return statusSpy.at(i)[1].value<SyncFileStatus>().tag();
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
fakeFolder.localModifier().insert(fooFileRootFolder);
|
||||
fakeFolder.localModifier().insert(barFileRootFolder);
|
||||
fakeFolder.localModifier().mkdir(QStringLiteral("subfolder"));
|
||||
fakeFolder.localModifier().insert(fooFileSubFolder);
|
||||
fakeFolder.localModifier().insert(barFileSubFolder);
|
||||
fakeFolder.localModifier().mkdir(QStringLiteral("aaa"));
|
||||
fakeFolder.localModifier().mkdir(QStringLiteral("aaa/subfolder"));
|
||||
fakeFolder.localModifier().insert(fooFileAaaSubFolder);
|
||||
fakeFolder.localModifier().insert(barFileAaaSubFolder);
|
||||
fakeFolder.localModifier().setModTime(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MTIME1));
|
||||
|
||||
fakeFolder.scheduleSync();
|
||||
fakeFolder.execUntilBeforePropagation();
|
||||
|
||||
QCOMPARE(checkStatus(), SyncFileStatus::StatusError);
|
||||
|
||||
fakeFolder.execUntilFinished();
|
||||
|
||||
fakeFolder.localModifier().setModTime(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
fakeFolder.localModifier().appendByte(barFileAaaSubFolder);
|
||||
fakeFolder.localModifier().setModTime(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MTIME1));
|
||||
|
||||
fakeFolder.scheduleSync();
|
||||
fakeFolder.execUntilBeforePropagation();
|
||||
|
||||
QCOMPARE(checkStatus(), SyncFileStatus::StatusError);
|
||||
|
||||
fakeFolder.execUntilFinished();
|
||||
|
||||
fakeFolder.localModifier().setModTime(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(CURRENT_MTIME));
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
fakeFolder.localModifier().appendByte(barFileAaaSubFolder);
|
||||
fakeFolder.localModifier().setModTime(barFileAaaSubFolder, QDateTime::fromSecsSinceEpoch(INVALID_MTIME2));
|
||||
|
||||
fakeFolder.scheduleSync();
|
||||
fakeFolder.execUntilBeforePropagation();
|
||||
|
||||
QCOMPARE(checkStatus(), SyncFileStatus::StatusError);
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_GUILESS_MAIN(TestSyncVirtualFiles)
|
||||
|
|
Loading…
Reference in a new issue