diff options
author | Olivier Goffart <ogoffart@woboq.com> | 2018-11-06 18:17:39 +0300 |
---|---|---|
committer | Olivier Goffart <ogoffart@woboq.com> | 2018-11-06 18:17:51 +0300 |
commit | 9b874c276483b4c68afed78cce7f74cee4c2333c (patch) | |
tree | 96ab9d904ab24cf7d8a5490a9181f9131a760523 /test | |
parent | 4b47fda7f664c9f6b223f072bbb9aadff8051978 (diff) | |
parent | c674d3957679bc88fd5c09647fe017f6411de595 (diff) |
Merge remote-tracking branch 'origin/2.5' into master
Conflicts:
src/libsync/propagateuploadng.cpp
test/CMakeLists.txt
Diffstat (limited to 'test')
-rw-r--r-- | test/CMakeLists.txt | 2 | ||||
-rw-r--r-- | test/testlockedfiles.cpp | 163 |
2 files changed, 165 insertions, 0 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1f078a665..1a26ace2e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -56,6 +56,8 @@ owncloud_add_test(LocalDiscovery "syncenginetestutils.h") owncloud_add_test(RemoteDiscovery "syncenginetestutils.h") owncloud_add_test(Permissions "syncenginetestutils.h") owncloud_add_test(SelectiveSync "syncenginetestutils.h") +owncloud_add_test(LockedFiles "syncenginetestutils.h;../src/gui/lockwatcher.cpp") + owncloud_add_test(FolderWatcher "${FolderWatcher_SRC}") if( UNIX AND NOT APPLE ) diff --git a/test/testlockedfiles.cpp b/test/testlockedfiles.cpp new file mode 100644 index 000000000..df1e8f8d0 --- /dev/null +++ b/test/testlockedfiles.cpp @@ -0,0 +1,163 @@ +/* + * 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 "lockwatcher.h" +#include <syncengine.h> +#include <localdiscoverytracker.h> + +using namespace OCC; + +#ifdef Q_OS_WIN +// pass combination of FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_DELETE +HANDLE makeHandle(const QString &file, int shareMode) +{ + const wchar_t *wuri = reinterpret_cast<const wchar_t *>(file.utf16()); + auto handle = CreateFileW( + wuri, + GENERIC_READ | GENERIC_WRITE, + shareMode, + NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (handle == INVALID_HANDLE_VALUE) { + qWarning() << GetLastError(); + } + return handle; +} +#endif + +class TestLockedFiles : public QObject +{ + Q_OBJECT + +private slots: + void testBasicLockFileWatcher() + { + int count = 0; + QString file; + + LockWatcher watcher; + watcher.setCheckInterval(std::chrono::milliseconds(50)); + connect(&watcher, &LockWatcher::fileUnlocked, &watcher, [&](const QString &f) { ++count; file = f; }); + + QString tmpFile; + { + QTemporaryFile tmp; + tmp.setAutoRemove(false); + tmp.open(); + tmpFile = tmp.fileName(); + } + QVERIFY(QFile::exists(tmpFile)); + + QVERIFY(!FileSystem::isFileLocked(tmpFile)); + watcher.addFile(tmpFile); + QVERIFY(watcher.contains(tmpFile)); + + QEventLoop loop; + QTimer::singleShot(120, &loop, [&] { loop.exit(); }); + loop.exec(); + + QCOMPARE(count, 1); + QCOMPARE(file, tmpFile); + QVERIFY(!watcher.contains(tmpFile)); + +#ifdef Q_OS_WIN + auto h = makeHandle(tmpFile, 0); + QVERIFY(FileSystem::isFileLocked(tmpFile)); + watcher.addFile(tmpFile); + + count = 0; + file.clear(); + QThread::msleep(120); + qApp->processEvents(); + + QCOMPARE(count, 0); + QVERIFY(file.isEmpty()); + QVERIFY(watcher.contains(tmpFile)); + + CloseHandle(h); + QVERIFY(!FileSystem::isFileLocked(tmpFile)); + + QThread::msleep(120); + qApp->processEvents(); + + QCOMPARE(count, 1); + QCOMPARE(file, tmpFile); + QVERIFY(!watcher.contains(tmpFile)); +#endif + QFile::remove(tmpFile); + } + +#ifdef Q_OS_WIN + void testLockedFilePropagation() + { + FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; + + QStringList seenLockedFiles; + connect(&fakeFolder.syncEngine(), &SyncEngine::seenLockedFile, &fakeFolder.syncEngine(), + [&](const QString &file) { seenLockedFiles.append(file); }); + + LocalDiscoveryTracker tracker; + connect(&fakeFolder.syncEngine(), &SyncEngine::itemCompleted, &tracker, &LocalDiscoveryTracker::slotItemCompleted); + connect(&fakeFolder.syncEngine(), &SyncEngine::finished, &tracker, &LocalDiscoveryTracker::slotSyncFinished); + auto hasLocalDiscoveryPath = [&](const QString &path) { + auto &paths = tracker.localDiscoveryPaths(); + return paths.find(path.toUtf8()) != paths.end(); + }; + + // + // Local change, attempted upload, but file is locked! + // + fakeFolder.localModifier().appendByte("A/a1"); + tracker.addTouchedPath("A/a1"); + auto h1 = makeHandle(fakeFolder.localPath() + "A/a1", 0); + + fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, tracker.localDiscoveryPaths()); + tracker.startSyncPartialDiscovery(); + QVERIFY(!fakeFolder.syncOnce()); + + QVERIFY(seenLockedFiles.contains(fakeFolder.localPath() + "A/a1")); + QVERIFY(seenLockedFiles.size() == 1); + QVERIFY(hasLocalDiscoveryPath("A/a1")); + + CloseHandle(h1); + + fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, tracker.localDiscoveryPaths()); + tracker.startSyncPartialDiscovery(); + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + + seenLockedFiles.clear(); + QVERIFY(tracker.localDiscoveryPaths().empty()); + + // + // Remote change, attempted download, but file is locked! + // + fakeFolder.remoteModifier().appendByte("A/a1"); + auto h2 = makeHandle(fakeFolder.localPath() + "A/a1", 0); + + fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, tracker.localDiscoveryPaths()); + tracker.startSyncPartialDiscovery(); + QVERIFY(!fakeFolder.syncOnce()); + + QVERIFY(seenLockedFiles.contains(fakeFolder.localPath() + "A/a1")); + QVERIFY(seenLockedFiles.size() == 1); + + CloseHandle(h2); + + fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, tracker.localDiscoveryPaths()); + tracker.startSyncPartialDiscovery(); + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } +#endif +}; + +QTEST_GUILESS_MAIN(TestLockedFiles) +#include "testlockedfiles.moc" |