From e20f258b6127aeedfec84fc69e9ede738daf9f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 17 Nov 2017 11:54:23 +0100 Subject: [PATCH] Add versioning to objectstore --- apps/files_trashbin/tests/StorageTest.php | 17 ++++ apps/files_versions/js/versioncollection.js | 8 +- apps/files_versions/js/versionmodel.js | 2 +- apps/files_versions/js/versionstabview.js | 3 +- apps/files_versions/lib/Storage.php | 10 +++ apps/files_versions/tests/VersioningTest.php | 11 +++ .../tests/js/versionmodelSpec.js | 3 +- core/js/files/client.js | 2 +- .../Files/Meta/MetaFileVersionNode.php | 5 +- lib/private/Files/Meta/MetaRootNode.php | 2 +- .../Files/Meta/MetaVersionCollection.php | 15 +++- .../Files/ObjectStore/ObjectStoreStorage.php | 62 ++++++++++++++ lib/private/Files/Storage/Common.php | 7 +- .../ObjectStore/IVersionedObjectStorage.php | 80 +++++++++++++++++++ .../Files/Storage/IVersionedStorage.php | 21 +++-- tests/lib/Files/MetaFilesTest.php | 10 ++- .../lib/Files/ObjectStore/ObjectStoreTest.php | 43 +++++++++- tests/lib/TestCase.php | 1 - 18 files changed, 273 insertions(+), 29 deletions(-) create mode 100644 lib/public/Files/ObjectStore/IVersionedObjectStorage.php diff --git a/apps/files_trashbin/tests/StorageTest.php b/apps/files_trashbin/tests/StorageTest.php index 576a8181410a..d8a6047909d4 100644 --- a/apps/files_trashbin/tests/StorageTest.php +++ b/apps/files_trashbin/tests/StorageTest.php @@ -28,9 +28,11 @@ namespace OCA\Files_Trashbin\Tests; +use OC\Files\ObjectStore\ObjectStoreStorage; use OC\Files\Filesystem; use OC\Files\Storage\Temporary; use OC\Files\View; +use OCP\Files\Storage; use Test\TestCase; use Test\Traits\UserTrait; @@ -299,6 +301,7 @@ public function testDeleteFolderAsReadOnlyRecipient() { * Test that deleted versions properly land in the trashbin. */ public function testDeleteVersionsOfFile() { + $this->markTestSkippedIfStorageHasOwnVersioning(); \OCA\Files_Versions\Hooks::connectHooks(); // trigger a version (multiple would not work because of the expire logic) @@ -328,6 +331,7 @@ public function testDeleteVersionsOfFile() { * Test that deleted versions properly land in the trashbin. */ public function testDeleteVersionsOfFolder() { + $this->markTestSkippedIfStorageHasOwnVersioning(); \OCA\Files_Versions\Hooks::connectHooks(); // trigger a version (multiple would not work because of the expire logic) @@ -363,6 +367,7 @@ public function testDeleteVersionsOfFolder() { * Test that deleted versions properly land in the trashbin when deleting as share recipient. */ public function testDeleteVersionsOfFileAsRecipient() { + $this->markTestSkippedIfStorageHasOwnVersioning(); \OCA\Files_Versions\Hooks::connectHooks(); $this->userView->mkdir('share'); @@ -415,6 +420,7 @@ public function testDeleteVersionsOfFileAsRecipient() { * Test that deleted versions properly land in the trashbin when deleting as share recipient. */ public function testDeleteVersionsOfFolderAsRecipient() { + $this->markTestSkippedIfStorageHasOwnVersioning(); \OCA\Files_Versions\Hooks::connectHooks(); $this->userView->mkdir('share'); @@ -483,6 +489,7 @@ public function testDeleteVersionsOfFolderAsRecipient() { * unlink() which should NOT trigger the version deletion logic. */ public function testKeepFileAndVersionsWhenMovingFileBetweenStorages() { + $this->markTestSkippedIfStorageHasOwnVersioning(); \OCA\Files_Versions\Hooks::connectHooks(); $storage2 = new Temporary([]); @@ -524,6 +531,7 @@ public function testKeepFileAndVersionsWhenMovingFileBetweenStorages() { * unlink() which should NOT trigger the version deletion logic. */ public function testKeepFileAndVersionsWhenMovingFolderBetweenStorages() { + $this->markTestSkippedIfStorageHasOwnVersioning(); \OCA\Files_Versions\Hooks::connectHooks(); $storage2 = new Temporary([]); @@ -564,6 +572,7 @@ public function testKeepFileAndVersionsWhenMovingFolderBetweenStorages() { * out of the shared folder */ public function testOwnerBackupWhenMovingFileOutOfShare() { + $this->markTestSkippedIfStorageHasOwnVersioning(); \OCA\Files_Versions\Hooks::connectHooks(); $this->userView->mkdir('share'); @@ -746,4 +755,12 @@ public function testSingleStorageDeleteFileLoggedOut() { $this->userView->unlink('test.txt'); } } + + private function markTestSkippedIfStorageHasOwnVersioning() { + /** @var Storage $storage */ + list($storage, $internalPath) = $this->userView->resolvePath('folder/inside.txt'); + if ($storage->instanceOfStorage(ObjectStoreStorage::class)) { + $this->markTestSkipped(); + } + } } diff --git a/apps/files_versions/js/versioncollection.js b/apps/files_versions/js/versioncollection.js index 5ec4e21586ea..47a26eeb8a04 100644 --- a/apps/files_versions/js/versioncollection.js +++ b/apps/files_versions/js/versioncollection.js @@ -38,19 +38,17 @@ parse: function(result) { var fullPath = this._fileInfo.getFullPath(); var fileId = this._fileInfo.get('id'); - var results = _.map(result, function(version) { - var revision = parseInt(version.id, 10); + return _.map(result, function(version) { + var revision = version.id; return { id: revision, name: revision, fullPath: fullPath, - timestamp: revision, - versionId: revision, + timestamp: moment(new Date(version['{DAV:}getlastmodified'])).format('X'), size: version['{DAV:}getcontentlength'], fileId: fileId }; }); - return results; } }); diff --git a/apps/files_versions/js/versionmodel.js b/apps/files_versions/js/versionmodel.js index 5551aa2430d2..5310cd719696 100644 --- a/apps/files_versions/js/versionmodel.js +++ b/apps/files_versions/js/versionmodel.js @@ -57,7 +57,7 @@ getDownloadUrl: function() { return OC.linkToRemoteBase('dav') + '/meta/' + encodeURIComponent(this.get('fileId')) + '/v/' + - encodeURIComponent(this.get('versionId')); + encodeURIComponent(this.get('id')); } }); diff --git a/apps/files_versions/js/versionstabview.js b/apps/files_versions/js/versionstabview.js index 1faaf2d89884..8a77f1bfc075 100644 --- a/apps/files_versions/js/versionstabview.js +++ b/apps/files_versions/js/versionstabview.js @@ -10,7 +10,7 @@ (function() { var TEMPLATE_ITEM = - '
  • ' + + '
  • ' + '
    ' + '
    ' + '' + @@ -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 d4fe824b29df..4b8d261f4955 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 c7392ec6e0d0..74eb80cea880 100644 --- a/apps/files_versions/tests/VersioningTest.php +++ b/apps/files_versions/tests/VersioningTest.php @@ -35,7 +35,9 @@ require_once __DIR__ . '/../appinfo/app.php'; +use OC\Files\ObjectStore\ObjectStoreStorage; use OC\Files\Storage\Temporary; +use OCP\Files\Storage; use Test\TestCase; /** @@ -873,6 +875,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'); @@ -918,6 +922,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 71c10725882c..7ead704b6bb6 100644 --- a/apps/files_versions/tests/js/versionmodelSpec.js +++ b/apps/files_versions/tests/js/versionmodelSpec.js @@ -19,13 +19,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 }); currentUserStub = sinon.stub(OC, 'getCurrentUser').returns({uid: '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 9d9fb61f24b3..8d1d9fb90bd7 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 { @@ -428,4 +430,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 2933812d283f..2711d9739c1f 100644 --- a/lib/private/Files/Storage/Common.php +++ b/lib/private/Files/Storage/Common.php @@ -696,7 +696,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))); @@ -739,4 +739,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/ObjectStoreTest.php b/tests/lib/Files/ObjectStore/ObjectStoreTest.php index c59ac0c758b1..c80b3f7c6352 100644 --- a/tests/lib/Files/ObjectStore/ObjectStoreTest.php +++ b/tests/lib/Files/ObjectStore/ObjectStoreTest.php @@ -2,7 +2,11 @@ /** * @author Thomas Müller * +<<<<<<< HEAD * @copyright Copyright (c) 2018, ownCloud GmbH +======= + * @copyright Copyright (c) 2017, ownCloud GmbH +>>>>>>> 478c4d51eb... Add versioning to objectstore * @license AGPL-3.0 * * This code is free software: you can redistribute it and/or modify @@ -27,6 +31,7 @@ use OC\Files\ObjectStore\ObjectStoreStorage; use OCP\Files\NotFoundException; use OCP\Files\ObjectStore\IObjectStore; +use OCP\Files\ObjectStore\IVersionedObjectStorage; use Test\TestCase; /** @@ -38,14 +43,14 @@ */ class ObjectStoreTest extends TestCase { - /** @var IObjectStore | \PHPUnit_Framework_MockObject_MockObject */ + /** @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); + $this->impl = $this->createMock([IObjectStore::class, IVersionedObjectStorage::class]); $this->impl->expects($this->any()) ->method('getStorageId') ->willReturn('object-store-test'); @@ -135,7 +140,7 @@ public function testMoveFromStorageWithObjectStore() { $this->objectStore = $this->getMockBuilder(ObjectStoreStorage::class) ->setMethods(['getUpdater']) - ->setConstructorArgs([[ 'objectstore' => $this->impl]]) + ->setConstructorArgs([['objectstore' => $this->impl]]) ->getMock(); $updater = $this->createMock(Updater::class); @@ -144,4 +149,36 @@ public function testMoveFromStorageWithObjectStore() { $targetInternalPath = 'foo/bar.txt'; $this->assertEquals(true, $this->objectStore->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath)); } + + /** + * @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/TestCase.php b/tests/lib/TestCase.php index 6c21b0a07e83..4eb7fb7ee360 100644 --- a/tests/lib/TestCase.php +++ b/tests/lib/TestCase.php @@ -544,5 +544,4 @@ public function runsWithPrimaryObjectstorage() { } return false; } - }