' +
'
' +
@@ -186,6 +186,7 @@
var timestamp = version.get('timestamp') * 1000;
var size = version.has('size') ? version.get('size') : 0;
return _.extend({
+ versionId: version.get('id'),
formattedTimestamp: OC.Util.formatDate(timestamp),
relativeTimestamp: OC.Util.relativeModifiedDate(timestamp),
humanReadableSize: OC.Util.humanFileSize(size, true),
diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php
index 130be95b22e3..37cb5b023f67 100644
--- a/apps/files_versions/lib/Storage.php
+++ b/apps/files_versions/lib/Storage.php
@@ -46,6 +46,7 @@
use OCA\Files_Versions\AppInfo\Application;
use OCA\Files_Versions\Command\Expire;
use OCP\Files\NotFoundException;
+use OCP\Files\Storage\IVersionedStorage;
use OCP\Lock\ILockingProvider;
use OCP\User;
@@ -174,7 +175,16 @@ public static function store($filename) {
}
list($uid, $filename) = self::getUidAndFilename($filename);
+ /** @var \OCP\Files\Storage\IStorage $storage */
+ list($storage, $internalPath) = Filesystem::resolvePath($filename);
+ if ($storage->instanceOfStorage(IVersionedStorage::class)) {
+ /** @var IVersionedStorage $storage */
+ if ($storage->saveVersion($internalPath)) {
+ return true;
+ }
+ }
+ // fallback implementation below - need to go into class Common
$files_view = new View('/'.$uid .'/files');
$users_view = new View('/'.$uid);
diff --git a/apps/files_versions/tests/VersioningTest.php b/apps/files_versions/tests/VersioningTest.php
index 13c1e8f5a492..3e5e3865ed39 100644
--- a/apps/files_versions/tests/VersioningTest.php
+++ b/apps/files_versions/tests/VersioningTest.php
@@ -34,7 +34,9 @@
require_once __DIR__ . '/../appinfo/app.php';
+use OC\Files\ObjectStore\ObjectStoreStorage;
use OC\Files\Storage\Temporary;
+use OCP\Files\Storage;
use Test\TestCase;
/**
@@ -676,6 +678,8 @@ public function testStoreVersionAsAnonymous() {
* @param string $path
*/
private function createAndCheckVersions(\OC\Files\View $view, $path) {
+ $this->markTestSkippedIfStorageHasOwnVersioning();
+
$view->file_put_contents($path, 'test file');
$view->file_put_contents($path, 'version 1');
$view->file_put_contents($path, 'version 2');
@@ -721,6 +725,13 @@ public static function loginHelper($user, $create = false) {
\OC::$server->getUserFolder($user);
}
+ private function markTestSkippedIfStorageHasOwnVersioning() {
+ /** @var Storage $storage */
+ list($storage, $internalPath) = $this->rootView->resolvePath(self::USERS_VERSIONS_ROOT);
+ if ($storage->instanceOfStorage(ObjectStoreStorage::class)) {
+ $this->markTestSkipped();
+ }
+ }
}
// extend the original class to make it possible to test protected methods
diff --git a/apps/files_versions/tests/js/versionmodelSpec.js b/apps/files_versions/tests/js/versionmodelSpec.js
index 3aeaecab7cec..ef4e07c23638 100644
--- a/apps/files_versions/tests/js/versionmodelSpec.js
+++ b/apps/files_versions/tests/js/versionmodelSpec.js
@@ -18,13 +18,12 @@ describe('OCA.Versions.VersionModel', function() {
beforeEach(function() {
model = new VersionModel({
- id: 10000000,
+ id: 123456789,
fileId: 10000000,
timestamp: 10000000,
fullPath: '/subdir/some file.txt',
name: 'some file.txt',
size: 150,
- versionId: 123456789
});
OC.currentUser = 'user0';
diff --git a/core/js/files/client.js b/core/js/files/client.js
index 222f5cadf55a..66bcf7b3ce23 100644
--- a/core/js/files/client.js
+++ b/core/js/files/client.js
@@ -797,7 +797,7 @@
* @param {Object} [headers=null] additional headers
*
* @return {Promise} promise
- * @since 10.1.0
+ * @since 10.0.5
*/
copy: function(path, destinationPath, allowOverwrite, headers, options) {
return this._moveOrCopy('COPY', path, destinationPath, allowOverwrite, headers, options);
diff --git a/lib/private/Files/Meta/MetaFileVersionNode.php b/lib/private/Files/Meta/MetaFileVersionNode.php
index 8aa245baefff..4ab1b29320d7 100644
--- a/lib/private/Files/Meta/MetaFileVersionNode.php
+++ b/lib/private/Files/Meta/MetaFileVersionNode.php
@@ -106,8 +106,7 @@ public function copy($targetPath) {
if (!$target->isUpdateable()) {
throw new ForbiddenException("Cannot write to $targetPath", false);
}
- $this->storage->restoreVersion($this->internalPath, $this->versionId);
- return true;
+ return $this->storage->restoreVersion($this->internalPath, $this->versionId);
}
// for now we only allow restoring of a version
@@ -119,7 +118,7 @@ public function getMTime() {
}
public function getMimetype() {
- return isset($this->versionInfo['mime-type']) ? $this->versionInfo['mime-type'] : 'application/octet-stream';
+ return isset($this->versionInfo['mimetype']) ? $this->versionInfo['mimetype'] : 'application/octet-stream';
}
public function getEtag() {
diff --git a/lib/private/Files/Meta/MetaRootNode.php b/lib/private/Files/Meta/MetaRootNode.php
index dbf9a1f55f44..0162b309d7f1 100644
--- a/lib/private/Files/Meta/MetaRootNode.php
+++ b/lib/private/Files/Meta/MetaRootNode.php
@@ -118,7 +118,7 @@ public function isCreatable() {
* @inheritdoc
*/
public function getPath() {
- return $this->getName();
+ return '/meta';
}
/**
diff --git a/lib/private/Files/Meta/MetaVersionCollection.php b/lib/private/Files/Meta/MetaVersionCollection.php
index 6b042643db84..8bcdb4985f21 100644
--- a/lib/private/Files/Meta/MetaVersionCollection.php
+++ b/lib/private/Files/Meta/MetaVersionCollection.php
@@ -81,9 +81,13 @@ public function getDirectoryListing() {
}
/** @var IVersionedStorage | Storage $storage */
$versions = $storage->getVersions($internalPath);
- return array_map(function($version) use ($storage, $internalPath) {
+ return array_values(array_map(function($version) use ($storage, $internalPath, $view, $path) {
+ if (!isset($version['mimetype'])) {
+ $version['mimetype'] = $view->getMimeType($path);
+ }
+
return new MetaFileVersionNode($this, $this->root, $version, $storage, $internalPath);
- }, $versions);
+ }, $versions));
}
/**
@@ -107,6 +111,9 @@ public function get($path) {
if ($version === null) {
throw new NotFoundException();
}
+ if (!isset($version['mimetype'])) {
+ $version['mimetype'] = $view->getMimeType($path);
+ }
return new MetaFileVersionNode($this, $this->root, $version, $storage, $internalPath);
}
@@ -120,4 +127,8 @@ public function getId() {
public function getName() {
return "v";
}
+
+ public function getPath() {
+ return "/meta/{$this->fileId}/v";
+ }
}
diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
index 735ff6fd9cb0..e7c487992e18 100644
--- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php
+++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
@@ -27,7 +27,9 @@
use Icewind\Streams\IteratorDirectory;
use OC\Files\Cache\CacheEntry;
+use OCP\Files\NotFoundException;
use OCP\Files\ObjectStore\IObjectStore;
+use OCP\Files\ObjectStore\IVersionedObjectStorage;
class ObjectStoreStorage extends \OC\Files\Storage\Common {
@@ -410,4 +412,64 @@ public function writeBack($tmpFile) {
public function hasUpdated($path, $time) {
return false;
}
+
+ public function saveVersion($internalPath) {
+ if ($this->objectStore instanceof IVersionedObjectStorage) {
+ $stat = $this->stat($internalPath);
+ // There are cases in the current implementation where saveVersion
+ // is called before the file was even written.
+ // There is nothing to be done in this case.
+ // We return true to not trigger the fallback implementation
+ if ($stat === false) {
+ return true;
+ }
+ return $this->objectStore->saveVersion($this->getURN($stat['fileid']));
+ }
+ return parent::saveVersion($internalPath);
+ }
+
+ public function getVersions($internalPath) {
+ if ($this->objectStore instanceof IVersionedObjectStorage) {
+ $stat = $this->stat($internalPath);
+ if ($stat === false) {
+ throw new NotFoundException();
+ }
+ return $this->objectStore->getVersions($this->getURN($stat['fileid']));
+ }
+ return parent::getVersions($internalPath);
+ }
+
+ public function getVersion($internalPath, $versionId) {
+ if ($this->objectStore instanceof IVersionedObjectStorage) {
+ $stat = $this->stat($internalPath);
+ if ($stat === false) {
+ throw new NotFoundException();
+ }
+ return $this->objectStore->getVersion($this->getURN($stat['fileid']), $versionId);
+ }
+ return parent::getVersion($internalPath, $versionId);
+ }
+
+ public function getContentOfVersion($internalPath, $versionId) {
+ if ($this->objectStore instanceof IVersionedObjectStorage) {
+ $stat = $this->stat($internalPath);
+ if ($stat === false) {
+ throw new NotFoundException();
+ }
+ return $this->objectStore->getContentOfVersion($this->getURN($stat['fileid']), $versionId);
+ }
+ return parent::getContentOfVersion($internalPath, $versionId);
+ }
+
+ public function restoreVersion($internalPath, $versionId) {
+ if ($this->objectStore instanceof IVersionedObjectStorage) {
+ $stat = $this->stat($internalPath);
+ if ($stat === false) {
+ throw new NotFoundException();
+ }
+ return $this->objectStore->restoreVersion($this->getURN($stat['fileid']), $versionId);
+ }
+ return parent::restoreVersion($internalPath, $versionId);
+ }
+
}
diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php
index ebca69b0c969..161ecda60de1 100644
--- a/lib/private/Files/Storage/Common.php
+++ b/lib/private/Files/Storage/Common.php
@@ -695,7 +695,7 @@ public function getVersions($internalPath) {
list ($uid, $filename) = $this->convertInternalPathToGlobalPath($internalPath);
return array_map(function ($version) use ($internalPath) {
- $version['mime-type'] = $this->getMimeType($internalPath);
+ $version['mimetype'] = $this->getMimeType($internalPath);
return $version;
}, array_values(
\OCA\Files_Versions\Storage::getVersions($uid, $filename)));
@@ -738,4 +738,9 @@ public function restoreVersion($internalPath, $versionId) {
$v = $this->getVersion($internalPath, $versionId);
return \OCA\Files_Versions\Storage::restoreVersion($v['owner'], $v['path'], $v['storage_location'], $versionId);
}
+
+ public function saveVersion($internalPath) {
+ // returning false here will trigger the fallback implementation
+ return false;
+ }
}
diff --git a/lib/public/Files/ObjectStore/IVersionedObjectStorage.php b/lib/public/Files/ObjectStore/IVersionedObjectStorage.php
new file mode 100644
index 000000000000..9cd048c3470e
--- /dev/null
+++ b/lib/public/Files/ObjectStore/IVersionedObjectStorage.php
@@ -0,0 +1,80 @@
+
+ *
+ * @copyright Copyright (c) 2017, ownCloud GmbH
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+
+namespace OCP\Files\ObjectStore;
+
+/**
+ * Interface IVersionedObjectStorage - storage layer to access version of an
+ * object living in an object store
+ *
+ * @package OCP\Files\ObjectStore
+ * @since 10.0.5
+ */
+interface IVersionedObjectStorage {
+
+ /**
+ * List all versions for the given file
+ *
+ * @param string $urn the unified resource name used to identify the object
+ * @return array
+ * @since 10.0.5
+ */
+ public function getVersions($urn);
+
+ /**
+ * Get one explicit version for the given file
+ *
+ * @param string $urn the unified resource name used to identify the object
+ * @param string $versionId
+ * @return array
+ * @since 10.0.5
+ */
+ public function getVersion($urn, $versionId);
+
+ /**
+ * Get the content of a given version of a given file as stream resource
+ *
+ * @param string $urn the unified resource name used to identify the object
+ * @param string $versionId
+ * @return resource
+ * @since 10.0.5
+ */
+ public function getContentOfVersion($urn, $versionId);
+
+ /**
+ * Restore the given version of a given file
+ *
+ * @param string $urn the unified resource name used to identify the object
+ * @param string $versionId
+ * @return boolean
+ * @since 10.0.5
+ */
+ public function restoreVersion($urn, $versionId);
+
+ /**
+ * Tells the storage to explicitly create a version of a given file
+ * @return boolean
+ * @since 10.0.5
+ */
+ public function saveVersion($internalPath);
+
+}
diff --git a/lib/public/Files/Storage/IVersionedStorage.php b/lib/public/Files/Storage/IVersionedStorage.php
index 55e60b501b83..a08035a4afaa 100644
--- a/lib/public/Files/Storage/IVersionedStorage.php
+++ b/lib/public/Files/Storage/IVersionedStorage.php
@@ -26,7 +26,7 @@
* Interface IVersionedStorage - storage layer to access version of a file
*
* @package OCP\Files\Storage
- * @since 10.1.0
+ * @since 10.0.5
*/
interface IVersionedStorage {
@@ -35,7 +35,7 @@ interface IVersionedStorage {
*
* @param string $internalPath
* @return array
- * @since 10.1.0
+ * @since 10.0.5
*/
public function getVersions($internalPath);
@@ -45,7 +45,7 @@ public function getVersions($internalPath);
* @param string $internalPath
* @param string $versionId
* @return array
- * @since 10.1.0
+ * @since 10.0.5
*/
public function getVersion($internalPath, $versionId);
@@ -55,7 +55,7 @@ public function getVersion($internalPath, $versionId);
* @param string $internalPath
* @param string $versionId
* @return resource
- * @since 10.1.0
+ * @since 10.0.5
*/
public function getContentOfVersion($internalPath, $versionId);
@@ -64,9 +64,18 @@ public function getContentOfVersion($internalPath, $versionId);
*
* @param string $internalPath
* @param string $versionId
- * @return void
- * @since 10.1.0
+ * @return boolean
+ * @since 10.0.5
*/
public function restoreVersion($internalPath, $versionId);
+ /**
+ * Tells the storage to explicitly create a version of a given file
+ *
+ * @param string $internalPath
+ * @return bool
+ * @since 10.0.5
+ */
+ public function saveVersion($internalPath);
+
}
diff --git a/tests/lib/Files/MetaFilesTest.php b/tests/lib/Files/MetaFilesTest.php
index 651736b4e427..0a01b3d0138e 100644
--- a/tests/lib/Files/MetaFilesTest.php
+++ b/tests/lib/Files/MetaFilesTest.php
@@ -69,15 +69,21 @@ public function testMetaInNodeAPI() {
$metaNodeOfFile = \OC::$server->getRootFolder()->get("meta");
$this->assertInstanceOf(MetaRootNode::class, $metaNodeOfFile);
$this->assertEquals([], $metaNodeOfFile->getDirectoryListing());
+ $this->assertEquals("/meta", $metaNodeOfFile->getPath());
+ $this->assertEquals("meta", $metaNodeOfFile->getName());
$metaNodeOfFile = \OC::$server->getRootFolder()->get("meta/{$info->getId()}");
$this->assertInstanceOf(MetaFileIdNode::class, $metaNodeOfFile);
+ $this->assertEquals("/meta/{$info->getId()}", $metaNodeOfFile->getPath());
+ $this->assertEquals("{$info->getId()}", $metaNodeOfFile->getName());
$children = $metaNodeOfFile->getDirectoryListing();
$this->assertEquals(1, count($children));
$this->assertInstanceOf(MetaVersionCollection::class, $children[0]);
$metaNodeOfFile = \OC::$server->getRootFolder()->get("meta/{$info->getId()}/v");
$this->assertInstanceOf(MetaVersionCollection::class, $metaNodeOfFile);
+ $this->assertEquals("/meta/{$info->getId()}/v", $metaNodeOfFile->getPath());
+ $this->assertEquals("v", $metaNodeOfFile->getName());
$children = $metaNodeOfFile->getDirectoryListing();
$this->assertEquals(0, count($children));
@@ -97,8 +103,8 @@ public function testMetaInNodeAPI() {
$this->assertEquals($file, $metaNodeOfFile->getContentDispositionFileName());
$this->assertEquals('text/plain', $metaNodeOfFile->getMimetype());
$this->assertEquals($info->getMTime(), $metaNodeOfFile->getMTime());
- $this->assertTrue(is_string($metaNodeOfFile->getMTime()));
- $this->assertTrue(strlen($metaNodeOfFile->getMTime()) > 0);
+ $this->assertTrue(is_string($metaNodeOfFile->getEtag()));
+ $this->assertTrue(strlen($metaNodeOfFile->getEtag()) > 0);
/** @var MetaFileVersionNode $metaNodeOfFile */
$this->assertEquals('1234', $metaNodeOfFile->getContent());
diff --git a/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php b/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php
new file mode 100644
index 000000000000..8408af5ffefc
--- /dev/null
+++ b/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php
@@ -0,0 +1,148 @@
+
+ *
+ */
+
+namespace Test\Files\ObjectStore;
+
+use OC\Files\ObjectStore\ObjectStoreStorage;
+use OC\Files\ObjectStore\Swift;
+
+/**
+ * Class ObjectStoreStorageTest
+ *
+ * @group DB
+ *
+ * @package Test\Files\Cache\ObjectStore
+ */
+abstract class ObjectStoreStorageTest extends \Test\Files\Storage\Storage {
+
+ 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 000000000000..0db7ad94efd4
--- /dev/null
+++ b/tests/lib/Files/ObjectStore/ObjectStoreTest.php
@@ -0,0 +1,150 @@
+
+ *
+ * @copyright Copyright (c) 2017, ownCloud GmbH
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace Test\Files\ObjectStore;
+
+use OC\Files\Cache\CacheEntry;
+use OC\Files\ObjectStore\NoopScanner;
+use OC\Files\ObjectStore\ObjectStoreStorage;
+use OCP\Files\NotFoundException;
+use OCP\Files\ObjectStore\IObjectStore;
+use OCP\Files\ObjectStore\IVersionedObjectStorage;
+use Test\TestCase;
+
+/**
+ * Class ObjectStoreTest
+ *
+ * @group DB
+ *
+ * @package Test\Files\ObjectStore
+ */
+class ObjectStoreTest extends TestCase {
+
+ /** @var IObjectStore | IVersionedObjectStorage | \PHPUnit_Framework_MockObject_MockObject */
+ private $impl;
+ /** @var ObjectStoreStorage | \PHPUnit_Framework_MockObject_MockObject */
+ private $objectStore;
+
+ public function setUp() {
+ parent::setUp();
+ $this->impl = $this->createMock([IObjectStore::class, IVersionedObjectStorage::class]);
+ $this->impl->expects($this->any())
+ ->method('getStorageId')
+ ->willReturn('object-store-test');
+ $this->objectStore = new ObjectStoreStorage([
+ 'objectstore' => $this->impl
+ ]);
+ }
+
+ public function testMkDir() {
+ $this->assertTrue($this->objectStore->mkdir('test'));
+ $cacheData = $this->objectStore->getCache()->get('test');
+ $this->assertInstanceOf(CacheEntry::class, $cacheData);
+ $this->assertEquals('test', $cacheData->getPath());
+ $this->assertEquals('httpd/unix-directory', $cacheData->getMimeType());
+ }
+
+ /**
+ * @depends testMkDir
+ */
+ public function testRmdir() {
+ $this->assertTrue($this->objectStore->rmdir('test'));
+ $this->assertFalse($this->objectStore->file_exists('test'));
+ }
+
+ public function testGetAndPutContents() {
+ $this->impl->expects($this->once())->method('writeObject');
+ $this->assertEquals(5, $this->objectStore->file_put_contents('test.txt', 'lorem'));
+
+ $stream = $this->createStreamFor('123456');
+
+ $this->impl->expects($this->once())->method('readObject')->willReturn($stream);
+ $this->assertEquals('123456', $this->objectStore->file_get_contents('test.txt'));
+ }
+
+ public function testGetScanner() {
+ $this->assertInstanceOf(NoopScanner::class, $this->objectStore->getScanner());
+ }
+
+ public function testUnlink() {
+ $this->impl->expects($this->once())->method('writeObject');
+ $this->assertTrue($this->objectStore->touch('to-unlink.txt'));
+
+ $this->impl->expects($this->once())->method('deleteObject');
+ $this->assertTrue($this->objectStore->unlink('to-unlink.txt'));
+ }
+
+ /**
+ * @dataProvider providersPathAndMime
+ * @param string $expectedMime
+ * @param string $path
+ */
+ public function testGetMime($expectedMime, $path) {
+ $this->assertTrue($this->objectStore->touch($path));
+ $this->assertEquals($expectedMime, $this->objectStore->getMimeType($path));
+
+ }
+
+ public function providersPathAndMime() {
+ return [
+ ['image/jpeg', 'sample.jpeg'],
+ ];
+ }
+
+ public function testRename() {
+ $this->assertTrue($this->objectStore->touch('alice.txt'));
+ $this->assertTrue($this->objectStore->rename('alice.txt', 'bob.txt'));
+ $this->assertFalse($this->objectStore->file_exists('alice.txt'));
+ $this->assertTrue($this->objectStore->file_exists('bob.txt'));
+ }
+
+ /**
+ * @dataProvider providesMethods
+ * @expectedException \OCP\Files\NotFoundException
+ */
+ public function testGetVersionsOfUnknownFile($method, $ignore = false) {
+ if ($ignore) {
+ throw new NotFoundException();
+ }
+ $this->impl->expects($this->never())->method($method)->willReturn([]);
+ $this->assertEquals([], $this->objectStore->$method('unknown-file.txt', '1'));
+ }
+
+ /**
+ * @dataProvider providesMethods
+ */
+ public function testGetVersions($method) {
+ $path = 'file-with-versions.txt';
+ $this->assertTrue($this->objectStore->touch($path));
+ $this->impl->expects($this->once())->method($method)->willReturn([]);
+ $this->assertEquals([], $this->objectStore->$method($path, '1'));
+ }
+
+ public function providesMethods() {
+ return [
+ 'saveVersion' => ['saveVersion', true],
+ 'getVersions' => ['getVersions'],
+ 'getVersion' => ['getVersion'],
+ 'getContentOfVersion' => ['getContentOfVersion'],
+ 'restoreVersion' => ['restoreVersion'],
+ ];
+ }
+}
diff --git a/tests/lib/Files/ObjectStore/SwiftTest.php b/tests/lib/Files/ObjectStore/SwiftTest.php
index cb89ed5ffac4..a83bcd8e9a7e 100644
--- a/tests/lib/Files/ObjectStore/SwiftTest.php
+++ b/tests/lib/Files/ObjectStore/SwiftTest.php
@@ -30,7 +30,7 @@
*
* @package Test\Files\Cache\ObjectStore
*/
-class SwiftTest extends \Test\Files\Storage\Storage {
+class SwiftTest extends ObjectStoreStorageTest {
/**
* @var Swift
@@ -82,117 +82,4 @@ protected function tearDown() {
}
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/TestCase.php b/tests/lib/TestCase.php
index f44b9877973b..23066994efd2 100644
--- a/tests/lib/TestCase.php
+++ b/tests/lib/TestCase.php
@@ -521,4 +521,15 @@ public function getCurrentUser() {
return $processUser['name'];
}
+ /**
+ * @param string $string
+ * @return bool|resource
+ */
+ protected function createStreamFor($string) {
+ $stream = fopen('php://memory', 'r+');
+ fwrite($stream, $string);
+ rewind($stream);
+ return $stream;
+ }
+
}