diff options
Diffstat (limited to 'apps/files_sharing')
-rw-r--r-- | apps/files_sharing/lib/sharedstorage.php | 4 | ||||
-rw-r--r-- | apps/files_sharing/lib/watcher.php | 27 | ||||
-rw-r--r-- | apps/files_sharing/tests/api.php | 111 | ||||
-rw-r--r-- | apps/files_sharing/tests/base.php | 143 | ||||
-rw-r--r-- | apps/files_sharing/tests/watcher.php | 161 |
5 files changed, 335 insertions, 111 deletions
diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 257da89c84e..6141d832199 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -43,7 +43,7 @@ class Shared extends \OC\Files\Storage\Common { * @param string Shared target file path * @return Returns array with the keys path, permissions, and owner or false if not found */ - private function getFile($target) { + public function getFile($target) { if (!isset($this->files[$target])) { // Check for partial files if (pathinfo($target, PATHINFO_EXTENSION) === 'part') { @@ -66,7 +66,7 @@ class Shared extends \OC\Files\Storage\Common { * @param string Shared target file path * @return string source file path or false if not found */ - private function getSourcePath($target) { + public function getSourcePath($target) { $source = $this->getFile($target); if ($source) { if (!isset($source['fullPath'])) { diff --git a/apps/files_sharing/lib/watcher.php b/apps/files_sharing/lib/watcher.php index 6fdfc1db36d..c40cf6911b8 100644 --- a/apps/files_sharing/lib/watcher.php +++ b/apps/files_sharing/lib/watcher.php @@ -32,9 +32,32 @@ class Shared_Watcher extends Watcher { * @param string $path */ public function checkUpdate($path) { - if ($path != '') { - parent::checkUpdate($path); + if ($path != '' && parent::checkUpdate($path)) { + // since checkUpdate() has already updated the size of the subdirs, + // only apply the update to the owner's parent dirs + + // find last parent before reaching the shared storage root, + // which is the actual shared dir from the owner + $sepPos = strpos($path, '/'); + if ($sepPos > 0) { + $baseDir = substr($path, 0, $sepPos); + } else { + $baseDir = $path; + } + + // find the path relative to the data dir + $file = $this->storage->getFile($baseDir); + $view = new \OC\Files\View('/' . $file['fileOwner']); + + // find the owner's storage and path + list($storage, $internalPath) = $view->resolvePath($file['path']); + + // update the parent dirs' sizes in the owner's cache + $storage->getCache()->correctFolderSize(dirname($internalPath)); + + return true; } + return false; } /** diff --git a/apps/files_sharing/tests/api.php b/apps/files_sharing/tests/api.php index 44fc4d8b7b3..1278e0c4d1f 100644 --- a/apps/files_sharing/tests/api.php +++ b/apps/files_sharing/tests/api.php @@ -20,90 +20,33 @@ * */ -require_once __DIR__ . '/../../../lib/base.php'; +require_once __DIR__ . '/base.php'; use OCA\Files\Share; /** * Class Test_Files_Sharing_Api */ -class Test_Files_Sharing_Api extends \PHPUnit_Framework_TestCase { - - const TEST_FILES_SHARING_API_USER1 = "test-share-user1"; - const TEST_FILES_SHARING_API_USER2 = "test-share-user2"; - const TEST_FILES_SHARING_API_USER3 = "test-share-user3"; - - public $stateFilesEncryption; - public $filename; - public $data; - /** - * @var OC_FilesystemView - */ - public $view; - public $folder; - - public static function setUpBeforeClass() { - // reset backend - \OC_User::clearBackends(); - \OC_User::useBackend('database'); - - // clear share hooks - \OC_Hook::clear('OCP\\Share'); - \OC::registerShareHooks(); - \OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup'); - - // create users - self::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1, true); - self::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, true); - self::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER3, true); - - } +class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { function setUp() { - - //login as user1 - \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); - - $this->data = 'foobar'; - $this->view = new \OC_FilesystemView('/' . \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1 . '/files'); + parent::setUp(); $this->folder = '/folder_share_api_test'; $this->filename = 'share-api-test.txt'; - // remember files_encryption state - $this->stateFilesEncryption = \OC_App::isEnabled('files_encryption'); - - //we don't want to tests with app files_encryption enabled - \OC_App::disable('files_encryption'); - - - $this->assertTrue(!\OC_App::isEnabled('files_encryption')); - // save file with content $this->view->file_put_contents($this->filename, $this->data); $this->view->mkdir($this->folder); $this->view->file_put_contents($this->folder.'/'.$this->filename, $this->data); - } function tearDown() { $this->view->unlink($this->filename); $this->view->deleteAll($this->folder); - // reset app files_encryption - if ($this->stateFilesEncryption) { - \OC_App::enable('files_encryption'); - } else { - \OC_App::disable('files_encryption'); - } - } - - public static function tearDownAfterClass() { - // cleanup users - \OC_User::deleteUser(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); - \OC_User::deleteUser(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2); - \OC_User::deleteUser(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER3); + parent::tearDown(); } /** @@ -548,50 +491,4 @@ class Test_Files_Sharing_Api extends \PHPUnit_Framework_TestCase { $this->assertTrue(empty($itemsAfterDelete)); } - - /** - * @param $user - * @param bool $create - * @param bool $password - */ - private static function loginHelper($user, $create = false, $password = false) { - if ($create) { - \OC_User::createUser($user, $user); - } - - if ($password === false) { - $password = $user; - } - - \OC_Util::tearDownFS(); - \OC_User::setUserId(''); - \OC\Files\Filesystem::tearDown(); - \OC_Util::setupFS($user); - \OC_User::setUserId($user); - - $params['uid'] = $user; - $params['password'] = $password; - } - - /** - * @brief get some information from a given share - * @param int $shareID - * @return array with: item_source, share_type, share_with, item_type, permissions - */ - private function getShareFromId($shareID) { - $sql = 'SELECT `item_source`, `share_type`, `share_with`, `item_type`, `permissions` FROM `*PREFIX*share` WHERE `id` = ?'; - $args = array($shareID); - $query = \OCP\DB::prepare($sql); - $result = $query->execute($args); - - $share = Null; - - if ($result && $result->numRows() > 0) { - $share = $result->fetchRow(); - } - - return $share; - - } - } diff --git a/apps/files_sharing/tests/base.php b/apps/files_sharing/tests/base.php new file mode 100644 index 00000000000..689c80cb9e6 --- /dev/null +++ b/apps/files_sharing/tests/base.php @@ -0,0 +1,143 @@ +<?php +/** + * ownCloud + * + * @author Bjoern Schiessle + * @copyright 2013 Bjoern Schiessle <schiessle@owncloud.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +require_once __DIR__ . '/../../../lib/base.php'; + +use OCA\Files\Share; + +/** + * Class Test_Files_Sharing_Base + * + * Base class for sharing tests. + */ +abstract class Test_Files_Sharing_Base extends \PHPUnit_Framework_TestCase { + + const TEST_FILES_SHARING_API_USER1 = "test-share-user1"; + const TEST_FILES_SHARING_API_USER2 = "test-share-user2"; + const TEST_FILES_SHARING_API_USER3 = "test-share-user3"; + + public $stateFilesEncryption; + public $filename; + public $data; + /** + * @var OC_FilesystemView + */ + public $view; + public $folder; + + public static function setUpBeforeClass() { + // reset backend + \OC_User::clearBackends(); + \OC_User::useBackend('database'); + + // clear share hooks + \OC_Hook::clear('OCP\\Share'); + \OC::registerShareHooks(); + \OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup'); + + // create users + self::loginHelper(self::TEST_FILES_SHARING_API_USER1, true); + self::loginHelper(self::TEST_FILES_SHARING_API_USER2, true); + self::loginHelper(self::TEST_FILES_SHARING_API_USER3, true); + + } + + function setUp() { + + //login as user1 + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $this->data = 'foobar'; + $this->view = new \OC_FilesystemView('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); + // remember files_encryption state + $this->stateFilesEncryption = \OC_App::isEnabled('files_encryption'); + + //we don't want to tests with app files_encryption enabled + \OC_App::disable('files_encryption'); + + + $this->assertTrue(!\OC_App::isEnabled('files_encryption')); + } + + function tearDown() { + // reset app files_encryption + if ($this->stateFilesEncryption) { + \OC_App::enable('files_encryption'); + } else { + \OC_App::disable('files_encryption'); + } + } + + public static function tearDownAfterClass() { + + // cleanup users + \OC_User::deleteUser(self::TEST_FILES_SHARING_API_USER1); + \OC_User::deleteUser(self::TEST_FILES_SHARING_API_USER2); + \OC_User::deleteUser(self::TEST_FILES_SHARING_API_USER3); + } + + /** + * @param $user + * @param bool $create + * @param bool $password + */ + protected static function loginHelper($user, $create = false, $password = false) { + if ($create) { + \OC_User::createUser($user, $user); + } + + if ($password === false) { + $password = $user; + } + + \OC_Util::tearDownFS(); + \OC_User::setUserId(''); + \OC\Files\Filesystem::tearDown(); + \OC_Util::setupFS($user); + \OC_User::setUserId($user); + + $params['uid'] = $user; + $params['password'] = $password; + } + + /** + * @brief get some information from a given share + * @param int $shareID + * @return array with: item_source, share_type, share_with, item_type, permissions + */ + protected function getShareFromId($shareID) { + $sql = 'SELECT `item_source`, `share_type`, `share_with`, `item_type`, `permissions` FROM `*PREFIX*share` WHERE `id` = ?'; + $args = array($shareID); + $query = \OCP\DB::prepare($sql); + $result = $query->execute($args); + + $share = Null; + + if ($result && $result->numRows() > 0) { + $share = $result->fetchRow(); + } + + return $share; + + } + +} diff --git a/apps/files_sharing/tests/watcher.php b/apps/files_sharing/tests/watcher.php new file mode 100644 index 00000000000..1a9a54cbcf8 --- /dev/null +++ b/apps/files_sharing/tests/watcher.php @@ -0,0 +1,161 @@ +<?php +/** + * ownCloud + * + * @author Vincent Petry + * @copyright 2013 Vincent Petry <pvince81@owncloud.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ +require_once __DIR__ . '/base.php'; + +class Test_Files_Sharing_Watcher extends Test_Files_Sharing_Base { + + function setUp() { + parent::setUp(); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + // prepare user1's dir structure + $textData = "dummy file data\n"; + $this->view->mkdir('container'); + $this->view->mkdir('container/shareddir'); + $this->view->mkdir('container/shareddir/subdir'); + + list($this->ownerStorage, $internalPath) = $this->view->resolvePath(''); + $this->ownerCache = $this->ownerStorage->getCache(); + $this->ownerStorage->getScanner()->scan(''); + + // share "shareddir" with user2 + $fileinfo = $this->view->getFileInfo('container/shareddir'); + \OCP\Share::shareItem('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER, + self::TEST_FILES_SHARING_API_USER2, 31); + + // login as user2 + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + // retrieve the shared storage + $secondView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2); + list($this->sharedStorage, $internalPath) = $secondView->resolvePath('files/Shared/shareddir'); + $this->sharedCache = $this->sharedStorage->getCache(); + } + + function tearDown() { + $this->sharedCache->clear(); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $fileinfo = $this->view->getFileInfo('container/shareddir'); + \OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER, + self::TEST_FILES_SHARING_API_USER2); + + $this->view->deleteAll('container'); + + $this->ownerCache->clear(); + + parent::tearDown(); + } + + /** + * Tests that writing a file using the shared storage will propagate the file + * size to the owner's parent folders. + */ + function testFolderSizePropagationToOwnerStorage() { + $initialSizes = self::getOwnerDirSizes('files/container/shareddir'); + + $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $dataLen = strlen($textData); + $this->sharedCache->put('shareddir/bar.txt', array('storage_mtime' => 10)); + $this->sharedStorage->file_put_contents('shareddir/bar.txt', $textData); + $this->sharedCache->put('shareddir', array('storage_mtime' => 10)); + + // run the propagation code + $result = $this->sharedStorage->getWatcher()->checkUpdate('shareddir'); + + $this->assertTrue($result); + + // the owner's parent dirs must have increase size + $newSizes = self::getOwnerDirSizes('files/container/shareddir'); + $this->assertEquals($initialSizes[''] + $dataLen, $newSizes['']); + $this->assertEquals($initialSizes['files'] + $dataLen, $newSizes['files']); + $this->assertEquals($initialSizes['files/container'] + $dataLen, $newSizes['files/container']); + $this->assertEquals($initialSizes['files/container/shareddir'] + $dataLen, $newSizes['files/container/shareddir']); + + // no more updates + $result = $this->sharedStorage->getWatcher()->checkUpdate('shareddir'); + + $this->assertFalse($result); + } + + /** + * Tests that writing a file using the shared storage will propagate the file + * size to the owner's parent folders. + */ + function testSubFolderSizePropagationToOwnerStorage() { + $initialSizes = self::getOwnerDirSizes('files/container/shareddir/subdir'); + + $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $dataLen = strlen($textData); + $this->sharedCache->put('shareddir/subdir/bar.txt', array('storage_mtime' => 10)); + $this->sharedStorage->file_put_contents('shareddir/subdir/bar.txt', $textData); + $this->sharedCache->put('shareddir/subdir', array('storage_mtime' => 10)); + + // run the propagation code + $result = $this->sharedStorage->getWatcher()->checkUpdate('shareddir/subdir'); + + $this->assertTrue($result); + + // the owner's parent dirs must have increase size + $newSizes = self::getOwnerDirSizes('files/container/shareddir/subdir'); + $this->assertEquals($initialSizes[''] + $dataLen, $newSizes['']); + $this->assertEquals($initialSizes['files'] + $dataLen, $newSizes['files']); + $this->assertEquals($initialSizes['files/container'] + $dataLen, $newSizes['files/container']); + $this->assertEquals($initialSizes['files/container/shareddir'] + $dataLen, $newSizes['files/container/shareddir']); + $this->assertEquals($initialSizes['files/container/shareddir/subdir'] + $dataLen, $newSizes['files/container/shareddir/subdir']); + + // no more updates + $result = $this->sharedStorage->getWatcher()->checkUpdate('shareddir/subdir'); + + $this->assertFalse($result); + } + + function testNoUpdateOnRoot() { + // no updates when called for root path + $result = $this->sharedStorage->getWatcher()->checkUpdate(''); + + $this->assertFalse($result); + + // FIXME: for some reason when running this "naked" test, + // there will be remaining nonsensical entries in the + // database with a path "test-share-user1/container/..." + } + + /** + * Returns the sizes of the path and its parent dirs in a hash + * where the key is the path and the value is the size. + */ + function getOwnerDirSizes($path) { + $result = array(); + + while ($path != '' && $path != '' && $path != '.') { + $cachedData = $this->ownerCache->get($path); + $result[$path] = $cachedData['size']; + $path = dirname($path); + } + $cachedData = $this->ownerCache->get(''); + $result[''] = $cachedData['size']; + return $result; + } +} |