Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libsync/syncengine.cpp8
-rw-r--r--test/CMakeLists.txt1
-rwxr-xr-xtest/scripts/txpl/t7.pl291
-rw-r--r--test/syncenginetestutils.h6
-rw-r--r--test/testpermissions.cpp306
5 files changed, 312 insertions, 300 deletions
diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp
index 05ad08777..41ea0320c 100644
--- a/src/libsync/syncengine.cpp
+++ b/src/libsync/syncengine.cpp
@@ -1532,14 +1532,6 @@ void SyncEngine::checkForPermission(SyncFileItemVector &syncItems)
RemotePermissions SyncEngine::getPermissions(const QString &file) const
{
- static bool isTest = qEnvironmentVariableIntValue("OWNCLOUD_TEST_PERMISSIONS");
- if (isTest) {
- QRegExp rx("_PERM_([^_]*)_[^/]*$");
- if (rx.indexIn(file) != -1) {
- return RemotePermissions(rx.cap(1));
- }
- }
-
// Fetch from the csync context while we still have it.
ASSERT(_csync_ctx->status != CSYNC_STATUS_INIT);
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 0ee8342c9..abad72e8c 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -52,6 +52,7 @@ owncloud_add_test(UploadReset "syncenginetestutils.h")
owncloud_add_test(AllFilesDeleted "syncenginetestutils.h")
owncloud_add_test(Blacklist "syncenginetestutils.h")
owncloud_add_test(LocalDiscovery "syncenginetestutils.h")
+owncloud_add_test(Permissions "syncenginetestutils.h")
owncloud_add_test(FolderWatcher "${FolderWatcher_SRC}")
if( UNIX AND NOT APPLE )
diff --git a/test/scripts/txpl/t7.pl b/test/scripts/txpl/t7.pl
deleted file mode 100755
index 6b68a06ef..000000000
--- a/test/scripts/txpl/t7.pl
+++ /dev/null
@@ -1,291 +0,0 @@
-#!/usr/bin/perl
-#
-# Test script for the ownCloud module of csync.
-# This script requires a running ownCloud instance accessible via HTTP.
-# It does quite some fancy tests and asserts the results.
-#
-# Copyright (C) by Klaas Freitag <freitag@owncloud.com>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-
-use lib ".";
-
-
-use File::Copy;
-use ownCloud::Test;
-
-use strict;
-
-print "Hello, this is t7, a tester for syncing of files in read only directory\n";
-
-# Check if the expected rows in the DB are non-empty. Note that in some cases they might be, then we cannot use this function
-# https://github.comowncloud/client/issues/2038
-sub assertCsyncJournalOk {
- my $path = $_[0];
-
- # FIXME: should test also remoteperm but it's not working with owncloud6
- # my $cmd = 'sqlite3 ' . $path . '._sync_*.db "SELECT count(*) from metadata where length(remotePerm) == 0 or length(fileId) == 0"';
- my $cmd = 'sqlite3 ' . $path . '._sync_*.db "SELECT count(*) from metadata where length(fileId) == 0"';
- my $result = `$cmd`;
- assert($result == "0");
-}
-
-# IMPORTANT NOTE :
-print "This test use the OWNCLOUD_TEST_PERMISSIONS environement variable and _PERM_xxx_ on filenames to set the permission. ";
-print "It does not rely on real permission set on the server. This test is just for testing the propagation choices\n";
-# "It would be nice" to have a test that test with real permissions on the server
-
-$ENV{OWNCLOUD_TEST_PERMISSIONS} = "1";
-
-initTesting();
-
-printInfo( "Init" );
-
-#create some files localy
-my $tmpdir = "/tmp/t7/";
-mkdir($tmpdir);
-createLocalFile( $tmpdir . "normalFile_PERM_WVND_.data", 100 );
-createLocalFile( $tmpdir . "cannotBeRemoved_PERM_WVN_.data", 101 );
-createLocalFile( $tmpdir . "canBeRemoved_PERM_D_.data", 102 );
-my $md5CanotBeModified = createLocalFile( $tmpdir . "canotBeModified_PERM_DVN_.data", 103 );
-createLocalFile( $tmpdir . "canBeModified_PERM_W_.data", 104 );
-
-#put them in some directories
-createRemoteDir( "normalDirectory_PERM_CKDNV_" );
-glob_put( "$tmpdir/*", "normalDirectory_PERM_CKDNV_" );
-createRemoteDir( "readonlyDirectory_PERM_M_" );
-glob_put( "$tmpdir/*", "readonlyDirectory_PERM_M_" );
-createRemoteDir( "readonlyDirectory_PERM_M_/subdir_PERM_CK_" );
-createRemoteDir( "readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_" );
-glob_put( "$tmpdir/normalFile_PERM_WVND_.data", "readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_" );
-
-
-csync();
-assertCsyncJournalOk(localDir());
-assertLocalAndRemoteDir( '', 0);
-
-system("sleep 1"); #make sure changes have different mtime
-
-printInfo( "Do some changes and see how they propagate" );
-
-#1. remove the file than cannot be removed
-# (they should be recovered)
-unlink( localDir() . 'normalDirectory_PERM_CKDNV_/cannotBeRemoved_PERM_WVN_.data' );
-unlink( localDir() . 'readonlyDirectory_PERM_M_/cannotBeRemoved_PERM_WVN_.data' );
-
-#2. remove the file that can be removed
-# (they should properly be gone)
-unlink( localDir() . 'normalDirectory_PERM_CKDNV_/canBeRemoved_PERM_D_.data' );
-unlink( localDir() . 'readonlyDirectory_PERM_M_/canBeRemoved_PERM_D_.data' );
-
-#3. Edit the files that cannot be modified
-# (they should be recovered, and a conflict shall be created)
-system("echo 'modified' > ". localDir() . "normalDirectory_PERM_CKDNV_/canotBeModified_PERM_DVN_.data");
-system("echo 'modified_' > ". localDir() . "readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN_.data");
-
-#4. Edit other files
-# (they should be uploaded)
-system("echo '__modified' > ". localDir() . "normalDirectory_PERM_CKDNV_/canBeModified_PERM_W_.data");
-system("echo '__modified_' > ". localDir() . "readonlyDirectory_PERM_M_/canBeModified_PERM_W_.data");
-
-#5. Create a new file in a read only folder
-# (should be uploaded)
-createLocalFile( localDir() . "normalDirectory_PERM_CKDNV_/newFile_PERM_WDNV_.data", 106 );
-
-#do the sync
-csync();
-assertCsyncJournalOk(localDir());
-
-#1.
-# File should be recovered
-assert( -e localDir(). 'normalDirectory_PERM_CKDNV_/cannotBeRemoved_PERM_WVN_.data' );
-assert( -e localDir(). 'readonlyDirectory_PERM_M_/cannotBeRemoved_PERM_WVN_.data' );
-
-#2.
-# File should be deleted
-assert( !-e localDir() . 'normalDirectory_PERM_CKDNV_/canBeRemoved_PERM_D_.data' );
-assert( !-e localDir() . 'readonlyDirectory_PERM_M_/canBeRemoved_PERM_D_.data' );
-
-#3.
-# File should be recovered
-assert($md5CanotBeModified eq md5OfFile( localDir().'normalDirectory_PERM_CKDNV_/canotBeModified_PERM_DVN_.data' ));
-assert($md5CanotBeModified eq md5OfFile( localDir().'readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN_.data' ));
-# and conflict created
-# TODO check that the conflict file has the right content
-assert( -e glob(localDir().'normalDirectory_PERM_CKDNV_/canotBeModified_PERM_DVN__conflict-*.data' ) );
-assert( -e glob(localDir().'readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN__conflict-*.data' ) );
-# remove the conflicts for the next assertLocalAndRemoteDir
-system("rm " . localDir().'normalDirectory_PERM_CKDNV_/canotBeModified_PERM_DVN__conflict-*.data' );
-system("rm " . localDir().'readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN__conflict-*.data' );
-
-#4. File should be updated, that's tested by assertLocalAndRemoteDir
-
-#5.
-# the file should be in the server and local
-assert( -e localDir() . "normalDirectory_PERM_CKDNV_/newFile_PERM_WDNV_.data" );
-
-### Both side should still be the same
-assertLocalAndRemoteDir( '', 0);
-
-# Next test
-
-#6. Create a new file in a read only folder
-# (they should not be uploaded)
-createLocalFile( localDir() . "readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data", 105 );
-
-# error: can't upload to readonly
-csync(1);
-assertCsyncJournalOk(localDir());
-
-#6.
-# The file should not exist on the remote
-# TODO: test that the file is NOT on the server
-# but still be there
-assert( -e localDir() . "readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data" );
-# remove it so assertLocalAndRemoteDir succeed.
-unlink(localDir() . "readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data");
-
-### Both side should still be the same
-assertLocalAndRemoteDir( '', 0);
-
-
-
-
-#######################################################################
-printInfo( "remove the read only directory" );
-# -> It must be recovered
-system("rm -r " . localDir().'readonlyDirectory_PERM_M_' );
-csync();
-assertCsyncJournalOk(localDir());
-assert( -e localDir(). 'readonlyDirectory_PERM_M_/cannotBeRemoved_PERM_WVN_.data' );
-assert( -e localDir(). 'readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data' );
-assertLocalAndRemoteDir( '', 0);
-
-
-#######################################################################
-printInfo( "move a directory in a outside read only folder" );
-system("sqlite3 " . localDir().'._sync_*.db .dump');
-
-#Missing directory should be restored
-#new directory should be uploaded
-system("mv " . localDir().'readonlyDirectory_PERM_M_/subdir_PERM_CK_ ' . localDir().'normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_' );
-
-csync();
-system("sqlite3 " . localDir().'._sync_*.db .dump');
-assertCsyncJournalOk(localDir());
-
-# old name restored
-assert( -e localDir(). 'readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_/' );
-assert( -e localDir(). 'readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data' );
-
-# new still exist
-assert( -e localDir(). 'normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data' );
-
-assertLocalAndRemoteDir( '', 0);
-
-
-
-
-
-#######################################################################
-printInfo( "rename a directory in a read only folder and move a directory to a read-only" );
-
-# do a sync to update the database
-csync();
-
-#1. rename a directory in a read only folder
-#Missing directory should be restored
-#new directory should stay but not be uploaded
-system("mv " . localDir().'readonlyDirectory_PERM_M_/subdir_PERM_CK_ ' . localDir().'readonlyDirectory_PERM_M_/newname_PERM_CK_' );
-
-#2. move a directory from read to read only (move the directory from previous step)
-system("mv " . localDir().'normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_ ' . localDir().'readonlyDirectory_PERM_M_/moved_PERM_CK_' );
-
-# error: can't upload to readonly!
-csync(1);
-assertCsyncJournalOk(localDir());
-
-#1.
-# old name restored
-assert( -e localDir(). 'readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data' );
-
-# new still exist
-assert( -e localDir(). 'readonlyDirectory_PERM_M_/newname_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data' );
-# but is not on server: so remove for assertLocalAndRemoteDir
-system("rm -r " . localDir(). "readonlyDirectory_PERM_M_/newname_PERM_CK_");
-
-#2.
-# old removed
-assert( ! -e localDir(). 'normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_/' );
-# new still there
-assert( -e localDir(). 'readonlyDirectory_PERM_M_/moved_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data' );
-#but not on server
-system("rm -r " . localDir(). "readonlyDirectory_PERM_M_/moved_PERM_CK_");
-
-assertLocalAndRemoteDir( '', 0);
-
-system("sqlite3 " . localDir().'._sync_*.db .dump');
-
-
-#######################################################################
-printInfo( "multiple restores of a file create different conflict files" );
-
-system("sleep 1"); #make sure changes have different mtime
-
-system("echo 'modified_1' > ". localDir() . "readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN_.data");
-
-#do the sync
-csync();
-assertCsyncJournalOk(localDir());
-
-system("sleep 1"); #make sure changes have different mtime
-
-system("echo 'modified_2' > ". localDir() . "readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN_.data");
-
-#do the sync
-csync();
-assertCsyncJournalOk(localDir());
-
-# there should be two conflict files
-# TODO check that the conflict file has the right content
-my @conflicts = glob(localDir().'readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN__conflict-*.data' );
-assert( scalar @conflicts == 2 );
-# remove the conflicts for the next assertLocalAndRemoteDir
-system("rm " . localDir().'readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN__conflict-*.data' );
-
-### Both side should still be the same
-assertLocalAndRemoteDir( '', 0);
-
-
-
-cleanup();
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/syncenginetestutils.h b/test/syncenginetestutils.h
index e0982bd15..536521b70 100644
--- a/test/syncenginetestutils.h
+++ b/test/syncenginetestutils.h
@@ -289,6 +289,7 @@ public:
QString name;
bool isDir = true;
bool isShared = false;
+ OCC::RemotePermissions permissions; // When uset, defaults to everything
QDateTime lastModified = QDateTime::currentDateTime().addDays(-7);
QString etag = generateEtag();
QByteArray fileId = generateFileId();
@@ -362,7 +363,9 @@ public:
xml.writeTextElement(davUri, QStringLiteral("getlastmodified"), stringDate);
xml.writeTextElement(davUri, QStringLiteral("getcontentlength"), QString::number(fileInfo.size));
xml.writeTextElement(davUri, QStringLiteral("getetag"), fileInfo.etag);
- xml.writeTextElement(ocUri, QStringLiteral("permissions"), fileInfo.isShared ? QStringLiteral("SRDNVCKW") : QStringLiteral("RDNVCKW"));
+ xml.writeTextElement(ocUri, QStringLiteral("permissions"), !fileInfo.permissions.isNull()
+ ? QString(fileInfo.permissions.toString())
+ : fileInfo.isShared ? QStringLiteral("SRDNVCKW") : QStringLiteral("RDNVCKW"));
xml.writeTextElement(ocUri, QStringLiteral("id"), fileInfo.fileId);
xml.writeTextElement(ocUri, QStringLiteral("checksums"), fileInfo.checksums);
buffer.write(fileInfo.extraDavProperties);
@@ -446,6 +449,7 @@ public:
emit uploadProgress(fileInfo->size, fileInfo->size);
setRawHeader("OC-ETag", fileInfo->etag.toLatin1());
setRawHeader("ETag", fileInfo->etag.toLatin1());
+ setRawHeader("OC-FileID", fileInfo->fileId);
setRawHeader("X-OC-MTime", "accepted"); // Prevents Q_ASSERT(!_runningNow) since we'll call PropagateItemJob::done twice in that case.
setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 200);
emit metaDataChanged();
diff --git a/test/testpermissions.cpp b/test/testpermissions.cpp
new file mode 100644
index 000000000..2fdd7c03a
--- /dev/null
+++ b/test/testpermissions.cpp
@@ -0,0 +1,306 @@
+/*
+ * 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>
+#include "common/ownsql.h"
+
+using namespace OCC;
+
+static void applyPermissionsFromName(FileInfo &info) {
+ static QRegularExpression rx("_PERM_([^_]*)_[^/]*$");
+ auto m = rx.match(info.name);
+ if (m.hasMatch()) {
+ info.permissions = RemotePermissions(m.captured(1));
+ }
+
+ for (FileInfo &sub : info.children)
+ applyPermissionsFromName(sub);
+}
+
+const FileInfo *findConflict(FileInfo &dir, const QString &filename)
+{
+ QFileInfo info(filename);
+ const FileInfo *parentDir = dir.find(info.path());
+ if (!parentDir) return nullptr;
+ QString start = info.baseName() + " (conflicted copy";
+ for (const auto &item : parentDir->children) {
+ if (item.name.startsWith(start)) {
+ return &item;
+ }
+ }
+ return nullptr;
+}
+
+// Check if the expected rows in the DB are non-empty. Note that in some cases they might be, then we cannot use this function
+// https://github.com/owncloud/client/issues/2038
+static void assertCsyncJournalOk(SyncJournalDb &journal)
+{
+ SqlDatabase db;
+ QVERIFY(db.openReadOnly(journal.databaseFilePath()));
+ SqlQuery q("SELECT count(*) from metadata where length(fileId) == 0", db);
+ QVERIFY(q.exec());
+ QVERIFY(q.next());
+ QCOMPARE(q.intValue(0), 0);
+#if defined(Q_OS_WIN) // Make sure the file does not appear in the FileInfo
+ FileSystem::setFileHidden(journal.databaseFilePath() + "-shm", true);
+#endif
+}
+
+
+class TestPermissions : public QObject
+{
+ Q_OBJECT
+
+private slots:
+
+ void t7pl()
+ {
+ FakeFolder fakeFolder{ FileInfo() };
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+ const int cannotBeModifiedSize = 133;
+ const int canBeModifiedSize = 144;
+
+ //create some files
+ auto insertIn = [&](const QString &dir) {
+ fakeFolder.remoteModifier().insert(dir + "normalFile_PERM_WVND_.data", 100 );
+ fakeFolder.remoteModifier().insert(dir + "cannotBeRemoved_PERM_WVN_.data", 101 );
+ fakeFolder.remoteModifier().insert(dir + "canBeRemoved_PERM_D_.data", 102 );
+ fakeFolder.remoteModifier().insert(dir + "cannotBeModified_PERM_DVN_.data", cannotBeModifiedSize , 'A');
+ fakeFolder.remoteModifier().insert(dir + "canBeModified_PERM_W_.data", canBeModifiedSize );
+ };
+
+ //put them in some directories
+ fakeFolder.remoteModifier().mkdir("normalDirectory_PERM_CKDNV_");
+ insertIn("normalDirectory_PERM_CKDNV_/");
+ fakeFolder.remoteModifier().mkdir("readonlyDirectory_PERM_M_" );
+ insertIn("readonlyDirectory_PERM_M_/" );
+ fakeFolder.remoteModifier().mkdir("readonlyDirectory_PERM_M_/subdir_PERM_CK_");
+ fakeFolder.remoteModifier().mkdir("readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_");
+ fakeFolder.remoteModifier().insert("readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data", 100);
+ applyPermissionsFromName(fakeFolder.remoteModifier());
+
+ QVERIFY(fakeFolder.syncOnce());
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ assertCsyncJournalOk(fakeFolder.syncJournal());
+ qInfo("Do some changes and see how they propagate");
+
+ //1. remove the file than cannot be removed
+ // (they should be recovered)
+ fakeFolder.localModifier().remove("normalDirectory_PERM_CKDNV_/cannotBeRemoved_PERM_WVN_.data");
+ fakeFolder.localModifier().remove("readonlyDirectory_PERM_M_/cannotBeRemoved_PERM_WVN_.data");
+
+ //2. remove the file that can be removed
+ // (they should properly be gone)
+ auto removeReadOnly = [&] (const QString &file) {
+ QVERIFY(!QFileInfo(fakeFolder.localPath() + file).permission(QFile::WriteOwner));
+ QFile(fakeFolder.localPath() + file).setPermissions(QFile::WriteOwner | QFile::ReadOwner);
+ fakeFolder.localModifier().remove(file);
+ };
+ removeReadOnly("normalDirectory_PERM_CKDNV_/canBeRemoved_PERM_D_.data");
+ removeReadOnly("readonlyDirectory_PERM_M_/canBeRemoved_PERM_D_.data");
+
+ //3. Edit the files that cannot be modified
+ // (they should be recovered, and a conflict shall be created)
+ auto editReadOnly = [&] (const QString &file) {
+ QVERIFY(!QFileInfo(fakeFolder.localPath() + file).permission(QFile::WriteOwner));
+ QFile(fakeFolder.localPath() + file).setPermissions(QFile::WriteOwner | QFile::ReadOwner);
+ fakeFolder.localModifier().appendByte(file);
+ };
+ editReadOnly("normalDirectory_PERM_CKDNV_/cannotBeModified_PERM_DVN_.data");
+ editReadOnly("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data");
+
+ //4. Edit other files
+ // (they should be uploaded)
+ fakeFolder.localModifier().appendByte("normalDirectory_PERM_CKDNV_/canBeModified_PERM_W_.data");
+ fakeFolder.localModifier().appendByte("readonlyDirectory_PERM_M_/canBeModified_PERM_W_.data");
+
+ //5. Create a new file in a read write folder
+ // (should be uploaded)
+ fakeFolder.localModifier().insert("normalDirectory_PERM_CKDNV_/newFile_PERM_WDNV_.data", 106 );
+ applyPermissionsFromName(fakeFolder.remoteModifier());
+
+ //do the sync
+ QVERIFY(fakeFolder.syncOnce());
+ assertCsyncJournalOk(fakeFolder.syncJournal());
+ auto currentLocalState = fakeFolder.currentLocalState();
+
+ //1.
+ // File should be recovered
+ QVERIFY(currentLocalState.find("normalDirectory_PERM_CKDNV_/cannotBeRemoved_PERM_WVN_.data"));
+ QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/cannotBeRemoved_PERM_WVN_.data"));
+
+ //2.
+ // File should be deleted
+ QVERIFY(!currentLocalState.find("normalDirectory_PERM_CKDNV_/canBeRemoved_PERM_D_.data"));
+ QVERIFY(!currentLocalState.find("readonlyDirectory_PERM_M_/canBeRemoved_PERM_D_.data"));
+
+ //3.
+ // File should be recovered
+ QCOMPARE(currentLocalState.find("normalDirectory_PERM_CKDNV_/cannotBeModified_PERM_DVN_.data")->size, cannotBeModifiedSize);
+ QCOMPARE(currentLocalState.find("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data")->size, cannotBeModifiedSize);
+ // and conflict created
+ auto c1 = findConflict(currentLocalState, "normalDirectory_PERM_CKDNV_/cannotBeModified_PERM_DVN_.data");
+ QVERIFY(c1);
+ QCOMPARE(c1->size, cannotBeModifiedSize + 1);
+ auto c2 = findConflict(currentLocalState, "readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data");
+ QVERIFY(c2);
+ QCOMPARE(c2->size, cannotBeModifiedSize + 1);
+ // remove the conflicts for the next state comparison
+ fakeFolder.localModifier().remove(c1->path());
+ fakeFolder.localModifier().remove(c2->path());
+
+ //4. File should be updated, that's tested by assertLocalAndRemoteDir
+ QCOMPARE(currentLocalState.find("normalDirectory_PERM_CKDNV_/canBeModified_PERM_W_.data")->size, canBeModifiedSize + 1);
+ QCOMPARE(currentLocalState.find("readonlyDirectory_PERM_M_/canBeModified_PERM_W_.data")->size, canBeModifiedSize + 1);
+
+ //5.
+ // the file should be in the server and local
+ QVERIFY(currentLocalState.find("normalDirectory_PERM_CKDNV_/newFile_PERM_WDNV_.data"));
+
+ // Both side should still be the same
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+ // Next test
+
+ //6. Create a new file in a read only folder
+ // (they should not be uploaded)
+ fakeFolder.localModifier().insert("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data", 105 );
+
+ applyPermissionsFromName(fakeFolder.remoteModifier());
+ // error: can't upload to readonly
+ QVERIFY(!fakeFolder.syncOnce());
+
+ assertCsyncJournalOk(fakeFolder.syncJournal());
+ currentLocalState = fakeFolder.currentLocalState();
+
+ //6.
+ // The file should not exist on the remote, but still be there
+ QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data"));
+ QVERIFY(!fakeFolder.currentRemoteState().find("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data"));
+ // remove it so next test succeed.
+ fakeFolder.localModifier().remove("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data");
+ // Both side should still be the same
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+
+ //######################################################################
+ qInfo( "remove the read only directory" );
+ // -> It must be recovered
+ fakeFolder.localModifier().remove("readonlyDirectory_PERM_M_");
+ applyPermissionsFromName(fakeFolder.remoteModifier());
+ QVERIFY(fakeFolder.syncOnce());
+ assertCsyncJournalOk(fakeFolder.syncJournal());
+ currentLocalState = fakeFolder.currentLocalState();
+ QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/cannotBeRemoved_PERM_WVN_.data"));
+ QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data"));
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+
+ //######################################################################
+ qInfo( "move a directory in a outside read only folder" );
+
+ //Missing directory should be restored
+ //new directory should be uploaded
+ fakeFolder.localModifier().rename("readonlyDirectory_PERM_M_/subdir_PERM_CK_", "normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_");
+ applyPermissionsFromName(fakeFolder.remoteModifier());
+ fakeFolder.syncOnce();
+ if (fakeFolder.syncEngine().isAnotherSyncNeeded() == ImmediateFollowUp) {
+ QVERIFY(fakeFolder.syncOnce());
+ }
+ assertCsyncJournalOk(fakeFolder.syncJournal());
+ currentLocalState = fakeFolder.currentLocalState();
+
+ // old name restored
+ QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_"));
+ QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data"));
+
+ // new still exist (and is uploaded)
+ QVERIFY(currentLocalState.find("normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data"));
+
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+ //######################################################################
+ qInfo( "rename a directory in a read only folder and move a directory to a read-only" );
+
+ // do a sync to update the database
+ applyPermissionsFromName(fakeFolder.remoteModifier());
+ QVERIFY(fakeFolder.syncOnce());
+
+ //1. rename a directory in a read only folder
+ //Missing directory should be restored
+ //new directory should stay but not be uploaded
+ fakeFolder.localModifier().rename("readonlyDirectory_PERM_M_/subdir_PERM_CK_", "readonlyDirectory_PERM_M_/newname_PERM_CK_" );
+
+ //2. move a directory from read to read only (move the directory from previous step)
+ fakeFolder.localModifier().rename("normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_", "readonlyDirectory_PERM_M_/moved_PERM_CK_" );
+
+ // error: can't upload to readonly!
+ QVERIFY(!fakeFolder.syncOnce());
+ if (fakeFolder.syncEngine().isAnotherSyncNeeded() == ImmediateFollowUp) {
+ QVERIFY(!fakeFolder.syncOnce());
+ }
+ assertCsyncJournalOk(fakeFolder.syncJournal());
+ currentLocalState = fakeFolder.currentLocalState();
+
+ //1.
+ // old name restored
+ QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" ));
+ // new still exist
+ QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/newname_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" ));
+ // but is not on server: so remove it localy for the future comarison
+ fakeFolder.localModifier().remove("readonlyDirectory_PERM_M_/newname_PERM_CK_");
+
+ //2.
+ // old removed
+ QVERIFY(!currentLocalState.find("normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_"));
+ // new still there
+ QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/moved_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" ));
+ //but not on server
+ fakeFolder.localModifier().remove("readonlyDirectory_PERM_M_/moved_PERM_CK_");
+
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+
+ //######################################################################
+ qInfo( "multiple restores of a file create different conflict files" );
+
+ editReadOnly("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data");
+ fakeFolder.localModifier().setContents("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data", 's');
+ //do the sync
+ applyPermissionsFromName(fakeFolder.remoteModifier());
+ QVERIFY(fakeFolder.syncOnce());
+ assertCsyncJournalOk(fakeFolder.syncJournal());
+
+ QThread::sleep(1); // make sure changes have different mtime
+ editReadOnly("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data");
+ fakeFolder.localModifier().setContents("readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data", 'd');
+
+ //do the sync
+ applyPermissionsFromName(fakeFolder.remoteModifier());
+ QVERIFY(fakeFolder.syncOnce());
+ assertCsyncJournalOk(fakeFolder.syncJournal());
+
+ // there should be two conflict files
+ currentLocalState = fakeFolder.currentLocalState();
+ int count = 0;
+ while (auto i = findConflict(currentLocalState, "readonlyDirectory_PERM_M_/cannotBeModified_PERM_DVN_.data")) {
+ QVERIFY((i->contentChar == 's') || (i->contentChar == 'd'));
+ fakeFolder.localModifier().remove(i->path());
+ currentLocalState = fakeFolder.currentLocalState();
+ count++;
+ }
+ QCOMPARE(count, 2);
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ }
+
+};
+
+QTEST_GUILESS_MAIN(TestPermissions)
+#include "testpermissions.moc"