diff options
-rw-r--r-- | lib/private/Files/ObjectStore/StorageObjectStore.php | 90 | ||||
-rw-r--r-- | tests/lib/Files/ObjectStore/LocalTest.php | 36 | ||||
-rw-r--r-- | tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php | 169 | ||||
-rw-r--r-- | tests/lib/Files/ObjectStore/ObjectStoreTest.php | 97 | ||||
-rw-r--r-- | tests/lib/Files/ObjectStore/SwiftTest.php | 194 |
5 files changed, 409 insertions, 177 deletions
diff --git a/lib/private/Files/ObjectStore/StorageObjectStore.php b/lib/private/Files/ObjectStore/StorageObjectStore.php new file mode 100644 index 00000000000..044243c1ee6 --- /dev/null +++ b/lib/private/Files/ObjectStore/StorageObjectStore.php @@ -0,0 +1,90 @@ +<?php +/** + * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Files\ObjectStore; + +use OCP\Files\ObjectStore\IObjectStore; +use OCP\Files\Storage\IStorage; + +/** + * Object store that wraps a storage backend, mostly for testing purposes + */ +class StorageObjectStore implements IObjectStore { + /** @var IStorage */ + private $storage; + + /** + * @param IStorage $storage + */ + public function __construct(IStorage $storage) { + $this->storage = $storage; + } + + /** + * @return string the container or bucket name where objects are stored + * @since 7.0.0 + */ + function getStorageId() { + $this->storage->getId(); + } + + /** + * @param string $urn the unified resource name used to identify the object + * @return resource stream with the read data + * @throws \Exception when something goes wrong, message will be logged + * @since 7.0.0 + */ + function readObject($urn) { + $handle = $this->storage->fopen($urn, 'r'); + if ($handle) { + return $handle; + } else { + throw new \Exception(); + } + } + + /** + * @param string $urn the unified resource name used to identify the object + * @param resource $stream stream with the data to write + * @throws \Exception when something goes wrong, message will be logged + * @since 7.0.0 + */ + function writeObject($urn, $stream) { + $handle = $this->storage->fopen($urn, 'w'); + if ($handle) { + stream_copy_to_stream($stream, $handle); + fclose($handle); + } else { + throw new \Exception(); + } + } + + /** + * @param string $urn the unified resource name used to identify the object + * @return void + * @throws \Exception when something goes wrong, message will be logged + * @since 7.0.0 + */ + function deleteObject($urn) { + $this->storage->unlink($urn); + } + +} diff --git a/tests/lib/Files/ObjectStore/LocalTest.php b/tests/lib/Files/ObjectStore/LocalTest.php new file mode 100644 index 00000000000..99aa23e065d --- /dev/null +++ b/tests/lib/Files/ObjectStore/LocalTest.php @@ -0,0 +1,36 @@ +<?php +/** + * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace Test\Files\ObjectStore; + +use OC\Files\ObjectStore\StorageObjectStore; +use OC\Files\Storage\Temporary; + +class LocalTest extends ObjectStoreTest { + /** + * @return \OCP\Files\ObjectStore\IObjectStore + */ + protected function getInstance() { + $storage = new Temporary(); + return new StorageObjectStore($storage); + } + +} diff --git a/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php b/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php new file mode 100644 index 00000000000..c9d6c1bd922 --- /dev/null +++ b/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php @@ -0,0 +1,169 @@ +<?php +/** + * @author Jörn Friedrich Dreyer + * @copyright (c) 2014 Jörn Friedrich Dreyer <jfd@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/>. + * + */ + +namespace Test\Files\ObjectStore; + +use OC\Files\ObjectStore\ObjectStoreStorage; +use OC\Files\ObjectStore\StorageObjectStore; +use OC\Files\Storage\Temporary; +use OCP\Files\ObjectStore\IObjectStore; +use Test\Files\Storage\Storage; + +/** + * @group DB + */ +class ObjectStoreStorageTest extends Storage { + + /** + * @var IObjectStore + */ + private $objectStorage; + + protected function setUp() { + parent::setUp(); + + $baseStorage = new Temporary(); + $this->objectStorage = new StorageObjectStore($baseStorage); + $config['objectstore'] = $this->objectStorage; + $this->instance = new ObjectStoreStorage($config); + } + + protected function tearDown() { + if (is_null($this->instance)) { + return; + } + $this->instance->getCache()->clear(); + + parent::tearDown(); + } + + public function testStat() { + + $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; + $ctimeStart = time(); + $this->instance->file_put_contents('/lorem.txt', file_get_contents($textFile)); + $this->assertTrue($this->instance->isReadable('/lorem.txt')); + $ctimeEnd = time(); + $mTime = $this->instance->filemtime('/lorem.txt'); + + // check that ($ctimeStart - 5) <= $mTime <= ($ctimeEnd + 1) + $this->assertGreaterThanOrEqual(($ctimeStart - 5), $mTime); + $this->assertLessThanOrEqual(($ctimeEnd + 1), $mTime); + $this->assertEquals(filesize($textFile), $this->instance->filesize('/lorem.txt')); + + $stat = $this->instance->stat('/lorem.txt'); + //only size and mtime are required in the result + $this->assertEquals($stat['size'], $this->instance->filesize('/lorem.txt')); + $this->assertEquals($stat['mtime'], $mTime); + + if ($this->instance->touch('/lorem.txt', 100) !== false) { + $mTime = $this->instance->filemtime('/lorem.txt'); + $this->assertEquals($mTime, 100); + } + } + + public function testCheckUpdate() { + $this->markTestSkipped('Detecting external changes is not supported on object storages'); + } + + /** + * @dataProvider copyAndMoveProvider + */ + public function testMove($source, $target) { + $this->initSourceAndTarget($source); + $sourceId = $this->instance->getCache()->getId(ltrim('/',$source)); + $this->assertNotEquals(-1, $sourceId); + + $this->instance->rename($source, $target); + + $this->assertTrue($this->instance->file_exists($target), $target.' was not created'); + $this->assertFalse($this->instance->file_exists($source), $source.' still exists'); + $this->assertSameAsLorem($target); + + $targetId = $this->instance->getCache()->getId(ltrim('/',$target)); + $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); + } + + public function testRenameDirectory() { + $this->instance->mkdir('source'); + $this->instance->file_put_contents('source/test1.txt', 'foo'); + $this->instance->file_put_contents('source/test2.txt', 'qwerty'); + $this->instance->mkdir('source/subfolder'); + $this->instance->file_put_contents('source/subfolder/test.txt', 'bar'); + $sourceId = $this->instance->getCache()->getId('source'); + $this->assertNotEquals(-1, $sourceId); + $this->instance->rename('source', 'target'); + + $this->assertFalse($this->instance->file_exists('source')); + $this->assertFalse($this->instance->file_exists('source/test1.txt')); + $this->assertFalse($this->instance->file_exists('source/test2.txt')); + $this->assertFalse($this->instance->file_exists('source/subfolder')); + $this->assertFalse($this->instance->file_exists('source/subfolder/test.txt')); + + $this->assertTrue($this->instance->file_exists('target')); + $this->assertTrue($this->instance->file_exists('target/test1.txt')); + $this->assertTrue($this->instance->file_exists('target/test2.txt')); + $this->assertTrue($this->instance->file_exists('target/subfolder')); + $this->assertTrue($this->instance->file_exists('target/subfolder/test.txt')); + + $this->assertEquals('foo', $this->instance->file_get_contents('target/test1.txt')); + $this->assertEquals('qwerty', $this->instance->file_get_contents('target/test2.txt')); + $this->assertEquals('bar', $this->instance->file_get_contents('target/subfolder/test.txt')); + $targetId = $this->instance->getCache()->getId('target'); + $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); + } + + public function testRenameOverWriteDirectory() { + $this->instance->mkdir('source'); + $this->instance->file_put_contents('source/test1.txt', 'foo'); + $sourceId = $this->instance->getCache()->getId('source'); + $this->assertNotEquals(-1, $sourceId); + + $this->instance->mkdir('target'); + $this->instance->file_put_contents('target/test1.txt', 'bar'); + $this->instance->file_put_contents('target/test2.txt', 'bar'); + + $this->instance->rename('source', 'target'); + + $this->assertFalse($this->instance->file_exists('source')); + $this->assertFalse($this->instance->file_exists('source/test1.txt')); + $this->assertFalse($this->instance->file_exists('target/test2.txt')); + $this->assertEquals('foo', $this->instance->file_get_contents('target/test1.txt')); + $targetId = $this->instance->getCache()->getId('target'); + $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); + } + + public function testRenameOverWriteDirectoryOverFile() { + $this->instance->mkdir('source'); + $this->instance->file_put_contents('source/test1.txt', 'foo'); + $sourceId = $this->instance->getCache()->getId('source'); + $this->assertNotEquals(-1, $sourceId); + + $this->instance->file_put_contents('target', 'bar'); + + $this->instance->rename('source', 'target'); + + $this->assertFalse($this->instance->file_exists('source')); + $this->assertFalse($this->instance->file_exists('source/test1.txt')); + $this->assertEquals('foo', $this->instance->file_get_contents('target/test1.txt')); + $targetId = $this->instance->getCache()->getId('target'); + $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); + } +} diff --git a/tests/lib/Files/ObjectStore/ObjectStoreTest.php b/tests/lib/Files/ObjectStore/ObjectStoreTest.php new file mode 100644 index 00000000000..2116306053e --- /dev/null +++ b/tests/lib/Files/ObjectStore/ObjectStoreTest.php @@ -0,0 +1,97 @@ +<?php + +/** + * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace Test\Files\ObjectStore; + +use Test\TestCase; + +abstract class ObjectStoreTest extends TestCase { + + /** + * @return \OCP\Files\ObjectStore\IObjectStore + */ + abstract protected function getInstance(); + + private function stringToStream($data) { + $stream = fopen('php://temp', 'w+'); + fwrite($stream, $data); + rewind($stream); + return $stream; + } + + public function testWriteRead() { + $stream = $this->stringToStream('foobar'); + + $instance = $this->getInstance(); + + $instance->writeObject('1', $stream); + + $result = $instance->readObject('1'); + $instance->deleteObject('1'); + + $this->assertEquals('foobar', stream_get_contents($result)); + + } + + public function testDelete() { + $stream = $this->stringToStream('foobar'); + + $instance = $this->getInstance(); + + $instance->writeObject('2', $stream); + + $instance->deleteObject('2'); + + try { + // to to read to verify that the object no longer exists + $instance->readObject('2'); + $this->fail(); + } catch (\Exception $e) { + // dummy assert to keep phpunit happy + $this->assertEquals(1, 1); + } + } + + public function testReadNonExisting() { + $instance = $this->getInstance(); + + try { + $instance->readObject('non-existing'); + $this->fail(); + } catch (\Exception $e) { + // dummy assert to keep phpunit happy + $this->assertEquals(1, 1); + } + } + + public function testDeleteNonExisting() { + $instance = $this->getInstance(); + + try { + $instance->deleteObject('non-existing'); + $this->fail(); + } catch (\Exception $e) { + // dummy assert to keep phpunit happy + $this->assertEquals(1, 1); + } + } +} diff --git a/tests/lib/Files/ObjectStore/SwiftTest.php b/tests/lib/Files/ObjectStore/SwiftTest.php index 9f69e040f87..f2aeace769c 100644 --- a/tests/lib/Files/ObjectStore/SwiftTest.php +++ b/tests/lib/Files/ObjectStore/SwiftTest.php @@ -1,198 +1,38 @@ <?php /** - * @author Jörn Friedrich Dreyer - * @copyright (c) 2014 Jörn Friedrich Dreyer <jfd@owncloud.com> + * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl> * - * 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. + * @license GNU AGPL version 3 or any later version * - * This library is distributed in the hope that it will be useful, + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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. + * 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/>. + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ namespace Test\Files\ObjectStore; -use OC\Files\ObjectStore\ObjectStoreStorage; use OC\Files\ObjectStore\Swift; -/** - * Class SwiftTest - * - * @group DB - * - * @package Test\Files\Cache\ObjectStore - */ -class SwiftTest extends \Test\Files\Storage\Storage { - +class SwiftTest extends ObjectStoreTest { /** - * @var Swift + * @return \OCP\Files\ObjectStore\IObjectStore */ - private $objectStorage; - - protected function setUp() { - parent::setUp(); - - if (!getenv('RUN_OBJECTSTORE_TESTS')) { - $this->markTestSkipped('objectstore tests are unreliable in some environments'); - } - - // reset backend - \OC_User::clearBackends(); - \OC_User::useBackend('database'); - - // create users - $users = array('test'); - foreach($users as $userName) { - $user = \OC::$server->getUserManager()->get($userName); - if ($user !== null) { $user->delete(); } - \OC::$server->getUserManager()->createUser($userName, $userName); - } - - // main test user - \OC_Util::tearDownFS(); - \OC_User::setUserId(''); - \OC\Files\Filesystem::tearDown(); - \OC_User::setUserId('test'); - + protected function getInstance() { $config = \OC::$server->getConfig()->getSystemValue('objectstore'); - $this->objectStorage = new Swift($config['arguments']); - $config['objectstore'] = $this->objectStorage; - $this->instance = new ObjectStoreStorage($config); - } - - protected function tearDown() { - if (is_null($this->instance)) { - return; - } - $this->objectStorage->deleteContainer(true); - $this->instance->getCache()->clear(); - - $users = array('test'); - foreach($users as $userName) { - $user = \OC::$server->getUserManager()->get($userName); - if ($user !== null) { $user->delete(); } - } - parent::tearDown(); - } - - public function testStat() { - - $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; - $ctimeStart = time(); - $this->instance->file_put_contents('/lorem.txt', file_get_contents($textFile)); - $this->assertTrue($this->instance->isReadable('/lorem.txt')); - $ctimeEnd = time(); - $mTime = $this->instance->filemtime('/lorem.txt'); - - // check that ($ctimeStart - 5) <= $mTime <= ($ctimeEnd + 1) - $this->assertGreaterThanOrEqual(($ctimeStart - 5), $mTime); - $this->assertLessThanOrEqual(($ctimeEnd + 1), $mTime); - $this->assertEquals(filesize($textFile), $this->instance->filesize('/lorem.txt')); - - $stat = $this->instance->stat('/lorem.txt'); - //only size and mtime are required in the result - $this->assertEquals($stat['size'], $this->instance->filesize('/lorem.txt')); - $this->assertEquals($stat['mtime'], $mTime); - - if ($this->instance->touch('/lorem.txt', 100) !== false) { - $mTime = $this->instance->filemtime('/lorem.txt'); - $this->assertEquals($mTime, 100); + if (!is_array($config) || $config['class'] !== 'OC\\Files\\ObjectStore\\Swift') { + $this->markTestSkipped('objectstore not configured for swift'); } - } - - public function testCheckUpdate() { - $this->markTestSkipped('Detecting external changes is not supported on object storages'); - } - - /** - * @dataProvider copyAndMoveProvider - */ - public function testMove($source, $target) { - $this->initSourceAndTarget($source); - $sourceId = $this->instance->getCache()->getId(ltrim('/',$source)); - $this->assertNotEquals(-1, $sourceId); - - $this->instance->rename($source, $target); - - $this->assertTrue($this->instance->file_exists($target), $target.' was not created'); - $this->assertFalse($this->instance->file_exists($source), $source.' still exists'); - $this->assertSameAsLorem($target); - - $targetId = $this->instance->getCache()->getId(ltrim('/',$target)); - $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); - } - - public function testRenameDirectory() { - $this->instance->mkdir('source'); - $this->instance->file_put_contents('source/test1.txt', 'foo'); - $this->instance->file_put_contents('source/test2.txt', 'qwerty'); - $this->instance->mkdir('source/subfolder'); - $this->instance->file_put_contents('source/subfolder/test.txt', 'bar'); - $sourceId = $this->instance->getCache()->getId('source'); - $this->assertNotEquals(-1, $sourceId); - $this->instance->rename('source', 'target'); - - $this->assertFalse($this->instance->file_exists('source')); - $this->assertFalse($this->instance->file_exists('source/test1.txt')); - $this->assertFalse($this->instance->file_exists('source/test2.txt')); - $this->assertFalse($this->instance->file_exists('source/subfolder')); - $this->assertFalse($this->instance->file_exists('source/subfolder/test.txt')); - - $this->assertTrue($this->instance->file_exists('target')); - $this->assertTrue($this->instance->file_exists('target/test1.txt')); - $this->assertTrue($this->instance->file_exists('target/test2.txt')); - $this->assertTrue($this->instance->file_exists('target/subfolder')); - $this->assertTrue($this->instance->file_exists('target/subfolder/test.txt')); - - $this->assertEquals('foo', $this->instance->file_get_contents('target/test1.txt')); - $this->assertEquals('qwerty', $this->instance->file_get_contents('target/test2.txt')); - $this->assertEquals('bar', $this->instance->file_get_contents('target/subfolder/test.txt')); - $targetId = $this->instance->getCache()->getId('target'); - $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); - } - - public function testRenameOverWriteDirectory() { - $this->instance->mkdir('source'); - $this->instance->file_put_contents('source/test1.txt', 'foo'); - $sourceId = $this->instance->getCache()->getId('source'); - $this->assertNotEquals(-1, $sourceId); - - $this->instance->mkdir('target'); - $this->instance->file_put_contents('target/test1.txt', 'bar'); - $this->instance->file_put_contents('target/test2.txt', 'bar'); - - $this->instance->rename('source', 'target'); - - $this->assertFalse($this->instance->file_exists('source')); - $this->assertFalse($this->instance->file_exists('source/test1.txt')); - $this->assertFalse($this->instance->file_exists('target/test2.txt')); - $this->assertEquals('foo', $this->instance->file_get_contents('target/test1.txt')); - $targetId = $this->instance->getCache()->getId('target'); - $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); - } - - public function testRenameOverWriteDirectoryOverFile() { - $this->instance->mkdir('source'); - $this->instance->file_put_contents('source/test1.txt', 'foo'); - $sourceId = $this->instance->getCache()->getId('source'); - $this->assertNotEquals(-1, $sourceId); - - $this->instance->file_put_contents('target', 'bar'); - - $this->instance->rename('source', 'target'); - $this->assertFalse($this->instance->file_exists('source')); - $this->assertFalse($this->instance->file_exists('source/test1.txt')); - $this->assertEquals('foo', $this->instance->file_get_contents('target/test1.txt')); - $targetId = $this->instance->getCache()->getId('target'); - $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); + return new Swift($config['arguments']); } } |