aboutsummaryrefslogtreecommitdiffstats
path: root/tests/lib/Files/ViewTest.php
diff options
context:
space:
mode:
Diffstat (limited to 'tests/lib/Files/ViewTest.php')
-rw-r--r--tests/lib/Files/ViewTest.php685
1 files changed, 424 insertions, 261 deletions
diff --git a/tests/lib/Files/ViewTest.php b/tests/lib/Files/ViewTest.php
index 2189e7c09f4..c490cd08dae 100644
--- a/tests/lib/Files/ViewTest.php
+++ b/tests/lib/Files/ViewTest.php
@@ -1,13 +1,14 @@
<?php
+
/**
- * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file. */
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
namespace Test\Files;
-use OCP\Cache\CappedMemoryCache;
+use OC\Files\Cache\Scanner;
use OC\Files\Cache\Watcher;
use OC\Files\Filesystem;
use OC\Files\Mount\MountPoint;
@@ -16,46 +17,75 @@ use OC\Files\Storage\Common;
use OC\Files\Storage\Storage;
use OC\Files\Storage\Temporary;
use OC\Files\View;
+use OC\Share20\ShareDisableChecker;
+use OCA\Files_Trashbin\Trash\ITrashManager;
+use OCP\Cache\CappedMemoryCache;
use OCP\Constants;
use OCP\Files\Config\IMountProvider;
+use OCP\Files\Config\IMountProviderCollection;
use OCP\Files\FileInfo;
+use OCP\Files\ForbiddenException;
use OCP\Files\GenericFileException;
+use OCP\Files\InvalidPathException;
use OCP\Files\Mount\IMountManager;
+use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorage;
+use OCP\Files\Storage\IStorageFactory;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\IGroup;
+use OCP\IGroupManager;
+use OCP\ITempManager;
+use OCP\IUser;
+use OCP\IUserManager;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
+use OCP\Server;
+use OCP\Share\IManager as IShareManager;
use OCP\Share\IShare;
use OCP\Util;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\HookHelper;
use Test\TestMoveableMountPoint;
use Test\Traits\UserTrait;
class TemporaryNoTouch extends Temporary {
- public function touch($path, $mtime = null) {
+ public function touch(string $path, ?int $mtime = null): bool {
return false;
}
}
class TemporaryNoCross extends Temporary {
- public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime = null) {
+ public function copyFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath, bool $preserveMtime = false): bool {
return Common::copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime);
}
- public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
+ public function moveFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath): bool {
return Common::moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
}
}
class TemporaryNoLocal extends Temporary {
- public function instanceOfStorage($className) {
- if ($className === '\OC\Files\Storage\Local') {
+ public function instanceOfStorage(string $class): bool {
+ if ($class === '\OC\Files\Storage\Local') {
return false;
} else {
- return parent::instanceOfStorage($className);
+ return parent::instanceOfStorage($class);
}
}
}
+class TestEventHandler {
+ public function umount() {
+ }
+ public function post_umount() {
+ }
+ public function preCallback() {
+ }
+ public function postCallback() {
+ }
+}
+
/**
* Class ViewTest
*
@@ -67,7 +97,7 @@ class ViewTest extends \Test\TestCase {
use UserTrait;
/**
- * @var \OC\Files\Storage\Storage[] $storages
+ * @var Storage[] $storages
*/
private $storages = [];
@@ -77,28 +107,28 @@ class ViewTest extends \Test\TestCase {
private $user;
/**
- * @var \OCP\IUser
+ * @var IUser
*/
private $userObject;
/**
- * @var \OCP\IGroup
+ * @var IGroup
*/
private $groupObject;
- /** @var \OC\Files\Storage\Storage */
+ /** @var Storage */
private $tempStorage;
protected function setUp(): void {
parent::setUp();
\OC_Hook::clear();
- \OC_User::clearBackends();
- \OC_User::useBackend(new \Test\Util\User\Dummy());
+ Server::get(IUserManager::class)->clearBackends();
+ Server::get(IUserManager::class)->registerBackend(new \Test\Util\User\Dummy());
//login
- $userManager = \OC::$server->getUserManager();
- $groupManager = \OC::$server->getGroupManager();
+ $userManager = Server::get(IUserManager::class);
+ $groupManager = Server::get(IGroupManager::class);
$this->user = 'test';
$this->userObject = $userManager->createUser('test', 'test');
@@ -108,7 +138,7 @@ class ViewTest extends \Test\TestCase {
self::loginAsUser($this->user);
/** @var IMountManager $manager */
- $manager = \OC::$server->get(IMountManager::class);
+ $manager = Server::get(IMountManager::class);
$manager->removeMount('/test');
$this->tempStorage = null;
@@ -129,13 +159,13 @@ class ViewTest extends \Test\TestCase {
self::logout();
/** @var SetupManager $setupManager */
- $setupManager = \OC::$server->get(SetupManager::class);
+ $setupManager = Server::get(SetupManager::class);
$setupManager->setupRoot();
$this->userObject->delete();
$this->groupObject->delete();
- $mountProviderCollection = \OC::$server->getMountProviderCollection();
+ $mountProviderCollection = Server::get(IMountProviderCollection::class);
self::invokePrivate($mountProviderCollection, 'providers', [[]]);
parent::tearDown();
@@ -144,7 +174,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testCacheAPI() {
+ public function testCacheAPI(): void {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$storage3 = $this->getTestStorage();
@@ -227,7 +257,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testGetPath() {
+ public function testGetPath(): void {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$storage3 = $this->getTestStorage();
@@ -254,8 +284,8 @@ class ViewTest extends \Test\TestCase {
}
- public function testGetPathNotExisting() {
- $this->expectException(\OCP\Files\NotFoundException::class);
+ public function testGetPathNotExisting(): void {
+ $this->expectException(NotFoundException::class);
$storage1 = $this->getTestStorage();
Filesystem::mount($storage1, [], '/');
@@ -271,7 +301,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testMountPointOverwrite() {
+ public function testMountPointOverwrite(): void {
$storage1 = $this->getTestStorage(false);
$storage2 = $this->getTestStorage();
$storage1->mkdir('substorage');
@@ -283,21 +313,19 @@ class ViewTest extends \Test\TestCase {
$this->assertCount(4, $folderContent);
}
- public function sharingDisabledPermissionProvider() {
+ public static function sharingDisabledPermissionProvider(): array {
return [
['no', '', true],
['yes', 'group1', false],
];
}
- /**
- * @dataProvider sharingDisabledPermissionProvider
- */
- public function testRemoveSharePermissionWhenSharingDisabledForUser($excludeGroups, $excludeGroupsList, $expectedShareable) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('sharingDisabledPermissionProvider')]
+ public function testRemoveSharePermissionWhenSharingDisabledForUser($excludeGroups, $excludeGroupsList, $expectedShareable): void {
// Reset sharing disabled for users cache
- self::invokePrivate(\OC::$server->getShareManager(), 'sharingDisabledForUsersCache', [new CappedMemoryCache()]);
+ self::invokePrivate(Server::get(ShareDisableChecker::class), 'sharingDisabledForUsersCache', [new CappedMemoryCache()]);
- $config = \OC::$server->getConfig();
+ $config = Server::get(IConfig::class);
$oldExcludeGroupsFlag = $config->getAppValue('core', 'shareapi_exclude_groups', 'no');
$oldExcludeGroupsList = $config->getAppValue('core', 'shareapi_exclude_groups_list', '');
$config->setAppValue('core', 'shareapi_exclude_groups', $excludeGroups);
@@ -320,10 +348,10 @@ class ViewTest extends \Test\TestCase {
$config->setAppValue('core', 'shareapi_exclude_groups_list', $oldExcludeGroupsList);
// Reset sharing disabled for users cache
- self::invokePrivate(\OC::$server->getShareManager(), 'sharingDisabledForUsersCache', [new CappedMemoryCache()]);
+ self::invokePrivate(Server::get(ShareDisableChecker::class), 'sharingDisabledForUsersCache', [new CappedMemoryCache()]);
}
- public function testCacheIncompleteFolder() {
+ public function testCacheIncompleteFolder(): void {
$storage1 = $this->getTestStorage(false);
Filesystem::mount($storage1, [], '/incomplete');
$rootView = new View('/incomplete');
@@ -336,7 +364,7 @@ class ViewTest extends \Test\TestCase {
$this->assertCount(1, $entries);
}
- public function testAutoScan() {
+ public function testAutoScan(): void {
$storage1 = $this->getTestStorage(false);
$storage2 = $this->getTestStorage(false);
Filesystem::mount($storage1, [], '/');
@@ -357,7 +385,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testSearch() {
+ public function testSearch(): void {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$storage3 = $this->getTestStorage();
@@ -407,7 +435,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testWatcher() {
+ public function testWatcher(): void {
$storage1 = $this->getTestStorage();
Filesystem::mount($storage1, [], '/');
$storage1->getWatcher()->setPolicy(Watcher::CHECK_ALWAYS);
@@ -428,7 +456,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testCopyBetweenStorageNoCross() {
+ public function testCopyBetweenStorageNoCross(): void {
$storage1 = $this->getTestStorage(true, TemporaryNoCross::class);
$storage2 = $this->getTestStorage(true, TemporaryNoCross::class);
$this->copyBetweenStorages($storage1, $storage2);
@@ -437,7 +465,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testCopyBetweenStorageCross() {
+ public function testCopyBetweenStorageCross(): void {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$this->copyBetweenStorages($storage1, $storage2);
@@ -446,7 +474,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testCopyBetweenStorageCrossNonLocal() {
+ public function testCopyBetweenStorageCrossNonLocal(): void {
$storage1 = $this->getTestStorage(true, TemporaryNoLocal::class);
$storage2 = $this->getTestStorage(true, TemporaryNoLocal::class);
$this->copyBetweenStorages($storage1, $storage2);
@@ -474,7 +502,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testMoveBetweenStorageNoCross() {
+ public function testMoveBetweenStorageNoCross(): void {
$storage1 = $this->getTestStorage(true, TemporaryNoCross::class);
$storage2 = $this->getTestStorage(true, TemporaryNoCross::class);
$this->moveBetweenStorages($storage1, $storage2);
@@ -483,7 +511,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testMoveBetweenStorageCross() {
+ public function testMoveBetweenStorageCross(): void {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$this->moveBetweenStorages($storage1, $storage2);
@@ -492,17 +520,17 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testMoveBetweenStorageCrossNonLocal() {
+ public function testMoveBetweenStorageCrossNonLocal(): void {
$storage1 = $this->getTestStorage(true, TemporaryNoLocal::class);
$storage2 = $this->getTestStorage(true, TemporaryNoLocal::class);
$this->moveBetweenStorages($storage1, $storage2);
}
public function moveBetweenStorages($storage1, $storage2) {
- Filesystem::mount($storage1, [], '/');
- Filesystem::mount($storage2, [], '/substorage');
+ Filesystem::mount($storage1, [], '/' . $this->user . '/');
+ Filesystem::mount($storage2, [], '/' . $this->user . '/substorage');
- $rootView = new View('');
+ $rootView = new View('/' . $this->user);
$rootView->rename('foo.txt', 'substorage/folder/foo.txt');
$this->assertFalse($rootView->file_exists('foo.txt'));
$this->assertTrue($rootView->file_exists('substorage/folder/foo.txt'));
@@ -515,7 +543,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testUnlink() {
+ public function testUnlink(): void {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
Filesystem::mount($storage1, [], '/');
@@ -535,14 +563,12 @@ class ViewTest extends \Test\TestCase {
$this->assertFalse($rootView->file_exists('substorage/bar.txt'));
}
- public function rmdirOrUnlinkDataProvider() {
+ public static function rmdirOrUnlinkDataProvider(): array {
return [['rmdir'], ['unlink']];
}
- /**
- * @dataProvider rmdirOrUnlinkDataProvider
- */
- public function testRmdir($method) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('rmdirOrUnlinkDataProvider')]
+ public function testRmdir($method): void {
$storage1 = $this->getTestStorage();
Filesystem::mount($storage1, [], '/');
@@ -561,7 +587,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testUnlinkRootMustFail() {
+ public function testUnlinkRootMustFail(): void {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
Filesystem::mount($storage1, [], '/');
@@ -580,7 +606,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testTouch() {
+ public function testTouch(): void {
$storage = $this->getTestStorage(true, TemporaryNoTouch::class);
Filesystem::mount($storage, [], '/');
@@ -604,7 +630,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testTouchFloat() {
+ public function testTouchFloat(): void {
$storage = $this->getTestStorage(true, TemporaryNoTouch::class);
Filesystem::mount($storage, [], '/');
@@ -621,7 +647,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testViewHooks() {
+ public function testViewHooks(): void {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$defaultRoot = Filesystem::getRoot();
@@ -646,7 +672,7 @@ class ViewTest extends \Test\TestCase {
$this->hookPath = $params['path'];
}
- public function testSearchNotOutsideView() {
+ public function testSearchNotOutsideView(): void {
$storage1 = $this->getTestStorage();
Filesystem::mount($storage1, [], '/');
$storage1->rename('folder', 'foo');
@@ -662,11 +688,11 @@ class ViewTest extends \Test\TestCase {
/**
* @param bool $scan
* @param string $class
- * @return \OC\Files\Storage\Storage
+ * @return Storage
*/
private function getTestStorage($scan = true, $class = Temporary::class) {
/**
- * @var \OC\Files\Storage\Storage $storage
+ * @var Storage $storage
*/
$storage = new $class([]);
$textData = "dummy file data\n";
@@ -687,7 +713,7 @@ class ViewTest extends \Test\TestCase {
/**
* @medium
*/
- public function testViewHooksIfRootStartsTheSame() {
+ public function testViewHooksIfRootStartsTheSame(): void {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$defaultRoot = Filesystem::getRoot();
@@ -718,7 +744,7 @@ class ViewTest extends \Test\TestCase {
$this->hookCreatePath = $params['path'];
}
- public function testEditNoCreateHook() {
+ public function testEditNoCreateHook(): void {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$defaultRoot = Filesystem::getRoot();
@@ -748,10 +774,8 @@ class ViewTest extends \Test\TestCase {
\OC_Hook::clear('OC_Filesystem', 'post_write');
}
- /**
- * @dataProvider resolvePathTestProvider
- */
- public function testResolvePath($expected, $pathToTest) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('resolvePathTestProvider')]
+ public function testResolvePath($expected, $pathToTest): void {
$storage1 = $this->getTestStorage();
Filesystem::mount($storage1, [], '/');
@@ -767,7 +791,7 @@ class ViewTest extends \Test\TestCase {
$this->assertTrue($exists);
}
- public function resolvePathTestProvider() {
+ public static function resolvePathTestProvider(): array {
return [
['foo.txt', 'foo.txt'],
['foo.txt', '/foo.txt'],
@@ -782,7 +806,7 @@ class ViewTest extends \Test\TestCase {
];
}
- public function testUTF8Names() {
+ public function testUTF8Names(): void {
$names = ['虚', '和知しゃ和で', 'regular ascii', 'sɨˈrɪlɪk', 'ѨѬ', 'أنا أحب القراءة كثيرا'];
$storage = new Temporary([]);
@@ -825,7 +849,7 @@ class ViewTest extends \Test\TestCase {
* 1024 is the max path length in mac
*/
$folderName = 'abcdefghijklmnopqrstuvwxyz012345678901234567890123456789';
- $tmpdirLength = strlen(\OC::$server->getTempManager()->getTemporaryFolder());
+ $tmpdirLength = strlen(Server::get(ITempManager::class)->getTemporaryFolder());
if (\OC_Util::runningOnMac()) {
$depth = ((1024 - $tmpdirLength) / 57);
} else {
@@ -861,7 +885,7 @@ class ViewTest extends \Test\TestCase {
}
}
- public function testTouchNotSupported() {
+ public function testTouchNotSupported(): void {
$storage = new TemporaryNoTouch([]);
$scanner = $storage->getScanner();
Filesystem::mount($storage, [], '/test/');
@@ -872,13 +896,13 @@ class ViewTest extends \Test\TestCase {
$info = $view->getFileInfo('/test/test');
$view->touch('/test/test', $past);
- $scanner->scanFile('test', \OC\Files\Cache\Scanner::REUSE_ETAG);
+ $scanner->scanFile('test', Scanner::REUSE_ETAG);
$info2 = $view->getFileInfo('/test/test');
$this->assertSame($info['etag'], $info2['etag']);
}
- public function testWatcherEtagCrossStorage() {
+ public function testWatcherEtagCrossStorage(): void {
$storage1 = new Temporary([]);
$storage2 = new Temporary([]);
$scanner1 = $storage1->getScanner();
@@ -910,29 +934,29 @@ class ViewTest extends \Test\TestCase {
$this->assertNotEquals($newFolderInfo->getEtag(), $oldEtag);
}
- /**
- * @dataProvider absolutePathProvider
- */
- public function testGetAbsolutePath($expectedPath, $relativePath) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('absolutePathProvider')]
+ public function testGetAbsolutePath($expectedPath, $relativePath): void {
$view = new View('/files');
$this->assertEquals($expectedPath, $view->getAbsolutePath($relativePath));
}
- public function testPartFileInfo() {
+ public function testPartFileInfo(): void {
$storage = new Temporary([]);
$scanner = $storage->getScanner();
Filesystem::mount($storage, [], '/test/');
- $storage->file_put_contents('test.part', 'foobar');
+ $sizeWritten = $storage->file_put_contents('test.part', 'foobar');
$scanner->scan('');
$view = new View('/test');
$info = $view->getFileInfo('test.part');
$this->assertInstanceOf('\OCP\Files\FileInfo', $info);
$this->assertNull($info->getId());
+ $this->assertEquals(6, $sizeWritten);
$this->assertEquals(6, $info->getSize());
+ $this->assertEquals('foobar', $view->file_get_contents('test.part'));
}
- public function absolutePathProvider() {
+ public static function absolutePathProvider(): array {
return [
['/files/', ''],
['/files/0', '0'],
@@ -944,32 +968,28 @@ class ViewTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider chrootRelativePathProvider
- */
- public function testChrootGetRelativePath($root, $absolutePath, $expectedPath) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('chrootRelativePathProvider')]
+ public function testChrootGetRelativePath($root, $absolutePath, $expectedPath): void {
$view = new View('/files');
$view->chroot($root);
$this->assertEquals($expectedPath, $view->getRelativePath($absolutePath));
}
- public function chrootRelativePathProvider() {
- return $this->relativePathProvider('/');
+ public static function chrootRelativePathProvider(): array {
+ return self::relativePathProvider('/');
}
- /**
- * @dataProvider initRelativePathProvider
- */
- public function testInitGetRelativePath($root, $absolutePath, $expectedPath) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('initRelativePathProvider')]
+ public function testInitGetRelativePath($root, $absolutePath, $expectedPath): void {
$view = new View($root);
$this->assertEquals($expectedPath, $view->getRelativePath($absolutePath));
}
- public function initRelativePathProvider() {
- return $this->relativePathProvider(null);
+ public static function initRelativePathProvider(): array {
+ return self::relativePathProvider(null);
}
- public function relativePathProvider($missingRootExpectedPath) {
+ public static function relativePathProvider($missingRootExpectedPath): array {
return [
// No root - returns the path
['', '/files', '/files'],
@@ -1040,7 +1060,7 @@ class ViewTest extends \Test\TestCase {
];
}
- public function testFileView() {
+ public function testFileView(): void {
$storage = new Temporary([]);
$scanner = $storage->getScanner();
$storage->file_put_contents('foo.txt', 'bar');
@@ -1056,11 +1076,9 @@ class ViewTest extends \Test\TestCase {
$this->assertEquals('foo', $view->file_get_contents(''));
}
- /**
- * @dataProvider tooLongPathDataProvider
- */
- public function testTooLongPath($operation, $param0 = null) {
- $this->expectException(\OCP\Files\InvalidPathException::class);
+ #[\PHPUnit\Framework\Attributes\DataProvider('tooLongPathDataProvider')]
+ public function testTooLongPath($operation, $param0 = null): void {
+ $this->expectException(InvalidPathException::class);
$longPath = '';
@@ -1089,14 +1107,13 @@ class ViewTest extends \Test\TestCase {
call_user_func([$rootView, $operation], $longPath, $param0);
}
- public function tooLongPathDataProvider() {
+ public static function tooLongPathDataProvider(): array {
return [
['getAbsolutePath'],
['getRelativePath'],
['getMountPoint'],
['resolvePath'],
['getLocalFile'],
- ['getLocalFolder'],
['mkdir'],
['rmdir'],
['opendir'],
@@ -1135,7 +1152,7 @@ class ViewTest extends \Test\TestCase {
];
}
- public function testRenameCrossStoragePreserveMtime() {
+ public function testRenameCrossStoragePreserveMtime(): void {
$storage1 = new Temporary([]);
$storage2 = new Temporary([]);
$storage1->mkdir('sub');
@@ -1160,11 +1177,11 @@ class ViewTest extends \Test\TestCase {
$this->assertEquals($time, $view->filemtime('/test/sub/storage/foo/bar.txt'));
}
- public function testRenameFailDeleteTargetKeepSource() {
+ public function testRenameFailDeleteTargetKeepSource(): void {
$this->doTestCopyRenameFail('rename');
}
- public function testCopyFailDeleteTargetKeepSource() {
+ public function testCopyFailDeleteTargetKeepSource(): void {
$this->doTestCopyRenameFail('copy');
}
@@ -1173,11 +1190,11 @@ class ViewTest extends \Test\TestCase {
/** @var \PHPUnit\Framework\MockObject\MockObject|Temporary $storage2 */
$storage2 = $this->getMockBuilder(TemporaryNoCross::class)
->setConstructorArgs([[]])
- ->setMethods(['fopen', 'writeStream'])
+ ->onlyMethods(['fopen', 'writeStream'])
->getMock();
$storage2->method('writeStream')
- ->willThrowException(new GenericFileException("Failed to copy stream"));
+ ->willThrowException(new GenericFileException('Failed to copy stream'));
$storage1->mkdir('sub');
$storage1->file_put_contents('foo.txt', '0123456789ABCDEFGH');
@@ -1215,11 +1232,11 @@ class ViewTest extends \Test\TestCase {
$this->assertFalse($storage2->getCache()->get('dirtomove/indir2.txt'));
}
- public function testDeleteFailKeepCache() {
+ public function testDeleteFailKeepCache(): void {
/** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */
$storage = $this->getMockBuilder(Temporary::class)
->setConstructorArgs([[]])
- ->setMethods(['unlink'])
+ ->onlyMethods(['unlink'])
->getMock();
$storage->expects($this->once())
->method('unlink')
@@ -1236,7 +1253,7 @@ class ViewTest extends \Test\TestCase {
$this->assertTrue($cache->inCache('foo.txt'));
}
- public function directoryTraversalProvider() {
+ public static function directoryTraversalProvider(): array {
return [
['../test/'],
['..\\test\\my/../folder'],
@@ -1245,16 +1262,16 @@ class ViewTest extends \Test\TestCase {
}
/**
- * @dataProvider directoryTraversalProvider
* @param string $root
*/
- public function testConstructDirectoryTraversalException($root) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('directoryTraversalProvider')]
+ public function testConstructDirectoryTraversalException($root): void {
$this->expectException(\Exception::class);
new View($root);
}
- public function testRenameOverWrite() {
+ public function testRenameOverWrite(): void {
$storage = new Temporary([]);
$scanner = $storage->getScanner();
$storage->mkdir('sub');
@@ -1267,36 +1284,36 @@ class ViewTest extends \Test\TestCase {
$this->assertTrue($view->rename('/test/foo.txt', '/test/foo/bar.txt'));
}
- public function testSetMountOptionsInStorage() {
+ public function testSetMountOptionsInStorage(): void {
$mount = new MountPoint(Temporary::class, '/asd/', [[]], Filesystem::getLoader(), ['foo' => 'bar']);
Filesystem::getMountManager()->addMount($mount);
- /** @var \OC\Files\Storage\Common $storage */
+ /** @var Common $storage */
$storage = $mount->getStorage();
$this->assertEquals($storage->getMountOption('foo'), 'bar');
}
- public function testSetMountOptionsWatcherPolicy() {
+ public function testSetMountOptionsWatcherPolicy(): void {
$mount = new MountPoint(Temporary::class, '/asd/', [[]], Filesystem::getLoader(), ['filesystem_check_changes' => Watcher::CHECK_NEVER]);
Filesystem::getMountManager()->addMount($mount);
- /** @var \OC\Files\Storage\Common $storage */
+ /** @var Common $storage */
$storage = $mount->getStorage();
$watcher = $storage->getWatcher();
$this->assertEquals(Watcher::CHECK_NEVER, $watcher->getPolicy());
}
- public function testGetAbsolutePathOnNull() {
+ public function testGetAbsolutePathOnNull(): void {
$view = new View();
$this->assertNull($view->getAbsolutePath(null));
}
- public function testGetRelativePathOnNull() {
+ public function testGetRelativePathOnNull(): void {
$view = new View();
$this->assertNull($view->getRelativePath(null));
}
- public function testNullAsRoot() {
- $this->expectException(\InvalidArgumentException::class);
+ public function testNullAsRoot(): void {
+ $this->expectException(\TypeError::class);
new View(null);
}
@@ -1305,13 +1322,13 @@ class ViewTest extends \Test\TestCase {
* e.g. reading from a folder that's being renamed
*
*
- * @dataProvider dataLockPaths
*
* @param string $rootPath
* @param string $pathPrefix
*/
- public function testReadFromWriteLockedPath($rootPath, $pathPrefix) {
- $this->expectException(\OCP\Lock\LockedException::class);
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataLockPaths')]
+ public function testReadFromWriteLockedPath($rootPath, $pathPrefix): void {
+ $this->expectException(LockedException::class);
$rootPath = str_replace('{folder}', 'files', $rootPath);
$pathPrefix = str_replace('{folder}', 'files', $pathPrefix);
@@ -1326,12 +1343,12 @@ class ViewTest extends \Test\TestCase {
/**
* Reading from a files_encryption folder that's being renamed
*
- * @dataProvider dataLockPaths
*
* @param string $rootPath
* @param string $pathPrefix
*/
- public function testReadFromWriteUnlockablePath($rootPath, $pathPrefix) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataLockPaths')]
+ public function testReadFromWriteUnlockablePath($rootPath, $pathPrefix): void {
$rootPath = str_replace('{folder}', 'files_encryption', $rootPath);
$pathPrefix = str_replace('{folder}', 'files_encryption', $pathPrefix);
@@ -1346,13 +1363,13 @@ class ViewTest extends \Test\TestCase {
* e.g. writing a file that's being downloaded
*
*
- * @dataProvider dataLockPaths
*
* @param string $rootPath
* @param string $pathPrefix
*/
- public function testWriteToReadLockedFile($rootPath, $pathPrefix) {
- $this->expectException(\OCP\Lock\LockedException::class);
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataLockPaths')]
+ public function testWriteToReadLockedFile($rootPath, $pathPrefix): void {
+ $this->expectException(LockedException::class);
$rootPath = str_replace('{folder}', 'files', $rootPath);
$pathPrefix = str_replace('{folder}', 'files', $pathPrefix);
@@ -1367,12 +1384,12 @@ class ViewTest extends \Test\TestCase {
/**
* Writing a file that's being downloaded
*
- * @dataProvider dataLockPaths
*
* @param string $rootPath
* @param string $pathPrefix
*/
- public function testWriteToReadUnlockableFile($rootPath, $pathPrefix) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataLockPaths')]
+ public function testWriteToReadUnlockableFile($rootPath, $pathPrefix): void {
$rootPath = str_replace('{folder}', 'files_encryption', $rootPath);
$pathPrefix = str_replace('{folder}', 'files_encryption', $pathPrefix);
@@ -1386,8 +1403,8 @@ class ViewTest extends \Test\TestCase {
/**
* Test that locks are on mount point paths instead of mount root
*/
- public function testLockLocalMountPointPathInsteadOfStorageRoot() {
- $lockingProvider = \OC::$server->getLockingProvider();
+ public function testLockLocalMountPointPathInsteadOfStorageRoot(): void {
+ $lockingProvider = Server::get(ILockingProvider::class);
$view = new View('/testuser/files/');
$storage = new Temporary([]);
Filesystem::mount($storage, [], '/');
@@ -1416,8 +1433,8 @@ class ViewTest extends \Test\TestCase {
/**
* Test that locks are on mount point paths and also mount root when requested
*/
- public function testLockStorageRootButNotLocalMountPoint() {
- $lockingProvider = \OC::$server->getLockingProvider();
+ public function testLockStorageRootButNotLocalMountPoint(): void {
+ $lockingProvider = Server::get(ILockingProvider::class);
$view = new View('/testuser/files/');
$storage = new Temporary([]);
Filesystem::mount($storage, [], '/');
@@ -1446,8 +1463,8 @@ class ViewTest extends \Test\TestCase {
/**
* Test that locks are on mount point paths and also mount root when requested
*/
- public function testLockMountPointPathFailReleasesBoth() {
- $lockingProvider = \OC::$server->getLockingProvider();
+ public function testLockMountPointPathFailReleasesBoth(): void {
+ $lockingProvider = Server::get(ILockingProvider::class);
$view = new View('/testuser/files/');
$storage = new Temporary([]);
Filesystem::mount($storage, [], '/');
@@ -1474,7 +1491,7 @@ class ViewTest extends \Test\TestCase {
$lockingProvider->releaseAll();
}
- public function dataLockPaths() {
+ public static function dataLockPaths(): array {
return [
['/testuser/{folder}', ''],
['/testuser', '/{folder}'],
@@ -1482,7 +1499,7 @@ class ViewTest extends \Test\TestCase {
];
}
- public function pathRelativeToFilesProvider() {
+ public static function pathRelativeToFilesProvider(): array {
return [
['admin/files', ''],
['admin/files/x', 'x'],
@@ -1494,15 +1511,13 @@ class ViewTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider pathRelativeToFilesProvider
- */
- public function testGetPathRelativeToFiles($path, $expectedPath) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('pathRelativeToFilesProvider')]
+ public function testGetPathRelativeToFiles($path, $expectedPath): void {
$view = new View();
$this->assertEquals($expectedPath, $view->getPathRelativeToFiles($path));
}
- public function pathRelativeToFilesProviderExceptionCases() {
+ public static function pathRelativeToFilesProviderExceptionCases(): array {
return [
[''],
['x'],
@@ -1513,10 +1528,10 @@ class ViewTest extends \Test\TestCase {
}
/**
- * @dataProvider pathRelativeToFilesProviderExceptionCases
* @param string $path
*/
- public function testGetPathRelativeToFilesWithInvalidArgument($path) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('pathRelativeToFilesProviderExceptionCases')]
+ public function testGetPathRelativeToFilesWithInvalidArgument($path): void {
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('$absolutePath must be relative to "files"');
@@ -1524,7 +1539,7 @@ class ViewTest extends \Test\TestCase {
$view->getPathRelativeToFiles($path);
}
- public function testChangeLock() {
+ public function testChangeLock(): void {
$view = new View('/testuser/files/');
$storage = new Temporary([]);
Filesystem::mount($storage, [], '/');
@@ -1545,7 +1560,7 @@ class ViewTest extends \Test\TestCase {
$this->assertFalse($this->isFileLocked($view, '/test//sub', ILockingProvider::LOCK_EXCLUSIVE));
}
- public function hookPathProvider() {
+ public static function hookPathProvider(): array {
return [
['/foo/files', '/foo', true],
['/foo/files/bar', '/foo', true],
@@ -1558,21 +1573,21 @@ class ViewTest extends \Test\TestCase {
}
/**
- * @dataProvider hookPathProvider
* @param $root
* @param $path
* @param $shouldEmit
*/
- public function testHookPaths($root, $path, $shouldEmit) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('hookPathProvider')]
+ public function testHookPaths($root, $path, $shouldEmit): void {
$filesystemReflection = new \ReflectionClass(Filesystem::class);
$defaultRootValue = $filesystemReflection->getProperty('defaultInstance');
$defaultRootValue->setAccessible(true);
$oldRoot = $defaultRootValue->getValue();
$defaultView = new View('/foo/files');
- $defaultRootValue->setValue($defaultView);
+ $defaultRootValue->setValue(null, $defaultView);
$view = new View($root);
$result = self::invokePrivate($view, 'shouldEmitHooks', [$path]);
- $defaultRootValue->setValue($oldRoot);
+ $defaultRootValue->setValue(null, $oldRoot);
$this->assertEquals($shouldEmit, $result);
}
@@ -1586,13 +1601,15 @@ class ViewTest extends \Test\TestCase {
$mounts = [];
foreach ($mountPoints as $mountPoint) {
$storage = $this->getMockBuilder(Storage::class)
- ->setMethods([])
- ->setConstructorArgs([[]])
+ ->onlyMethods([])
->getMock();
$storage->method('getId')->willReturn('non-null-id');
+ $storage->method('getStorageCache')->willReturnCallback(function () use ($storage) {
+ return new \OC\Files\Cache\Storage($storage, true, Server::get(IDBConnection::class));
+ });
$mounts[] = $this->getMockBuilder(TestMoveableMountPoint::class)
- ->setMethods(['moveMount'])
+ ->onlyMethods(['moveMount'])
->setConstructorArgs([$storage, $mountPoint])
->getMock();
}
@@ -1603,7 +1620,7 @@ class ViewTest extends \Test\TestCase {
->method('getMountsForUser')
->willReturn($mounts);
- $mountProviderCollection = \OC::$server->getMountProviderCollection();
+ $mountProviderCollection = Server::get(IMountProviderCollection::class);
$mountProviderCollection->registerProvider($mountProvider);
return $mounts;
@@ -1612,7 +1629,7 @@ class ViewTest extends \Test\TestCase {
/**
* Test mount point move
*/
- public function testMountPointMove() {
+ public function testMountPointMove(): void {
self::loginAsUser($this->user);
[$mount1, $mount2] = $this->createTestMovableMountPoints([
@@ -1634,10 +1651,7 @@ class ViewTest extends \Test\TestCase {
$this->assertTrue($view->rename('mount2', 'sub/moved_mount'), 'Can move a mount point into a subdirectory');
}
- /**
- * Test that moving a mount point into another is forbidden
- */
- public function testMoveMountPointIntoAnother() {
+ public function testMoveMountPointOverwrite(): void {
self::loginAsUser($this->user);
[$mount1, $mount2] = $this->createTestMovableMountPoints([
@@ -1653,53 +1667,94 @@ class ViewTest extends \Test\TestCase {
$view = new View('/' . $this->user . '/files/');
- $this->assertFalse($view->rename('mount1', 'mount2'), 'Cannot overwrite another mount point');
- $this->assertFalse($view->rename('mount1', 'mount2/sub'), 'Cannot move a mount point into another');
+ $this->expectException(ForbiddenException::class);
+ $view->rename('mount1', 'mount2');
+ }
+
+ public function testMoveMountPointIntoMount(): void {
+ self::loginAsUser($this->user);
+
+ [$mount1, $mount2] = $this->createTestMovableMountPoints([
+ $this->user . '/files/mount1',
+ $this->user . '/files/mount2',
+ ]);
+
+ $mount1->expects($this->never())
+ ->method('moveMount');
+
+ $mount2->expects($this->never())
+ ->method('moveMount');
+
+ $view = new View('/' . $this->user . '/files/');
+
+ $this->expectException(ForbiddenException::class);
+ $view->rename('mount1', 'mount2/sub');
}
/**
* Test that moving a mount point into a shared folder is forbidden
*/
- public function testMoveMountPointIntoSharedFolder() {
+ public function testMoveMountPointIntoSharedFolder(): void {
self::loginAsUser($this->user);
- [$mount1] = $this->createTestMovableMountPoints([
+ [$mount1, $mount2] = $this->createTestMovableMountPoints([
$this->user . '/files/mount1',
+ $this->user . '/files/mount2',
]);
$mount1->expects($this->never())
->method('moveMount');
+ $mount2->expects($this->once())
+ ->method('moveMount')
+ ->willReturn(true);
+
$view = new View('/' . $this->user . '/files/');
$view->mkdir('shareddir');
$view->mkdir('shareddir/sub');
$view->mkdir('shareddir/sub2');
+ // Create a similar named but non-shared folder
+ $view->mkdir('shareddir notshared');
$fileId = $view->getFileInfo('shareddir')->getId();
- $userObject = \OC::$server->getUserManager()->createUser('test2', 'IHateNonMockableStaticClasses');
+ $userObject = Server::get(IUserManager::class)->createUser('test2', 'IHateNonMockableStaticClasses');
$userFolder = \OC::$server->getUserFolder($this->user);
$shareDir = $userFolder->get('shareddir');
- $shareManager = \OC::$server->getShareManager();
+ $shareManager = Server::get(IShareManager::class);
$share = $shareManager->newShare();
$share->setSharedWith('test2')
->setSharedBy($this->user)
->setShareType(IShare::TYPE_USER)
- ->setPermissions(\OCP\Constants::PERMISSION_READ)
- ->setId(42)
- ->setProviderId('foo')
+ ->setPermissions(Constants::PERMISSION_READ)
->setNode($shareDir);
$shareManager->createShare($share);
- $this->assertFalse($view->rename('mount1', 'shareddir'), 'Cannot overwrite shared folder');
- $this->assertFalse($view->rename('mount1', 'shareddir/sub'), 'Cannot move mount point into shared folder');
- $this->assertFalse($view->rename('mount1', 'shareddir/sub/sub2'), 'Cannot move mount point into shared subfolder');
+ try {
+ $view->rename('mount1', 'shareddir');
+ $this->fail('Cannot overwrite shared folder');
+ } catch (ForbiddenException $e) {
+
+ }
+ try {
+ $view->rename('mount1', 'shareddir/sub');
+ $this->fail('Cannot move mount point into shared folder');
+ } catch (ForbiddenException $e) {
+
+ }
+ try {
+ $view->rename('mount1', 'shareddir/sub/sub2');
+ $this->fail('Cannot move mount point into shared subfolder');
+ } catch (ForbiddenException $e) {
+
+ }
+ $this->assertTrue($view->rename('mount2', 'shareddir notshared/sub'), 'Can move mount point into a similarly named but non-shared folder');
$shareManager->deleteShare($share);
$userObject->delete();
}
- public function basicOperationProviderForLocks() {
+ public static function basicOperationProviderForLocks(): array {
return [
// --- write hook ----
[
@@ -1739,6 +1794,8 @@ class ViewTest extends \Test\TestCase {
ILockingProvider::LOCK_SHARED,
ILockingProvider::LOCK_EXCLUSIVE,
ILockingProvider::LOCK_SHARED,
+ null,
+ 0,
],
// ---- delete hook ----
@@ -1770,6 +1827,8 @@ class ViewTest extends \Test\TestCase {
ILockingProvider::LOCK_SHARED,
ILockingProvider::LOCK_SHARED,
null,
+ null,
+ false,
],
[
'fopen',
@@ -1796,23 +1855,63 @@ class ViewTest extends \Test\TestCase {
// ---- no hooks, no locks ---
['is_dir', ['dir'], 'dir', null],
['is_file', ['dir'], 'dir', null],
- ['stat', ['dir'], 'dir', null],
- ['filetype', ['dir'], 'dir', null],
- ['filesize', ['dir'], 'dir', null],
+ [
+ 'stat',
+ ['dir'],
+ 'dir',
+ null,
+ ILockingProvider::LOCK_SHARED,
+ ILockingProvider::LOCK_SHARED,
+ ILockingProvider::LOCK_SHARED,
+ null,
+ false,
+ ],
+ [
+ 'filetype',
+ ['dir'],
+ 'dir',
+ null,
+ ILockingProvider::LOCK_SHARED,
+ ILockingProvider::LOCK_SHARED,
+ ILockingProvider::LOCK_SHARED,
+ null,
+ false,
+ ],
+ [
+ 'filesize',
+ ['dir'],
+ 'dir',
+ null,
+ ILockingProvider::LOCK_SHARED,
+ ILockingProvider::LOCK_SHARED,
+ ILockingProvider::LOCK_SHARED,
+ null,
+ /* Return an int */
+ 100
+ ],
['isCreatable', ['dir'], 'dir', null],
['isReadable', ['dir'], 'dir', null],
['isUpdatable', ['dir'], 'dir', null],
['isDeletable', ['dir'], 'dir', null],
['isSharable', ['dir'], 'dir', null],
['file_exists', ['dir'], 'dir', null],
- ['filemtime', ['dir'], 'dir', null],
+ [
+ 'filemtime',
+ ['dir'],
+ 'dir',
+ null,
+ ILockingProvider::LOCK_SHARED,
+ ILockingProvider::LOCK_SHARED,
+ ILockingProvider::LOCK_SHARED,
+ null,
+ false,
+ ],
];
}
/**
* Test whether locks are set before and after the operation
*
- * @dataProvider basicOperationProviderForLocks
*
* @param string $operation operation name on the view
* @param array $operationArgs arguments for the operation
@@ -1822,8 +1921,9 @@ class ViewTest extends \Test\TestCase {
* @param int $expectedLockDuring expected lock during operation
* @param int $expectedLockAfter expected lock during post hooks
* @param int $expectedStrayLock expected lock after returning, should
- * be null (unlock) for most operations
+ * be null (unlock) for most operations
*/
+ #[\PHPUnit\Framework\Attributes\DataProvider('basicOperationProviderForLocks')]
public function testLockBasicOperation(
$operation,
$operationArgs,
@@ -1832,15 +1932,21 @@ class ViewTest extends \Test\TestCase {
$expectedLockBefore = ILockingProvider::LOCK_SHARED,
$expectedLockDuring = ILockingProvider::LOCK_SHARED,
$expectedLockAfter = ILockingProvider::LOCK_SHARED,
- $expectedStrayLock = null
- ) {
+ $expectedStrayLock = null,
+ $returnValue = true,
+ ): void {
$view = new View('/' . $this->user . '/files/');
- /** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */
+ /** @var Temporary&MockObject $storage */
$storage = $this->getMockBuilder(Temporary::class)
- ->setMethods([$operation])
+ ->onlyMethods([$operation])
->getMock();
+ /* Pause trash to avoid the trashbin intercepting rmdir and unlink calls */
+ Server::get(ITrashManager::class)->pauseTrash();
+ /* Same thing with encryption wrapper */
+ Server::get(IStorageFactory::class)->removeStorageWrapper('oc_encryption');
+
Filesystem::mount($storage, [], $this->user . '/');
// work directly on disk because mkdir might be mocked
@@ -1853,10 +1959,10 @@ class ViewTest extends \Test\TestCase {
$storage->expects($this->once())
->method($operation)
->willReturnCallback(
- function () use ($view, $lockedPath, &$lockTypeDuring) {
+ function () use ($view, $lockedPath, &$lockTypeDuring, $returnValue) {
$lockTypeDuring = $this->getFileLockType($view, $lockedPath);
- return true;
+ return $returnValue;
}
);
@@ -1876,19 +1982,22 @@ class ViewTest extends \Test\TestCase {
}
$this->assertEquals($expectedStrayLock, $this->getFileLockType($view, $lockedPath));
+
+ /* Resume trash to avoid side effects */
+ Server::get(ITrashManager::class)->resumeTrash();
}
/**
* Test locks for file_put_content with stream.
* This code path uses $storage->fopen instead
*/
- public function testLockFilePutContentWithStream() {
+ public function testLockFilePutContentWithStream(): void {
$view = new View('/' . $this->user . '/files/');
$path = 'test_file_put_contents.txt';
/** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */
$storage = $this->getMockBuilder(Temporary::class)
- ->setMethods(['fopen'])
+ ->onlyMethods(['fopen'])
->getMock();
Filesystem::mount($storage, [], $this->user . '/');
@@ -1921,13 +2030,13 @@ class ViewTest extends \Test\TestCase {
/**
* Test locks for fopen with fclose at the end
*/
- public function testLockFopen() {
+ public function testLockFopen(): void {
$view = new View('/' . $this->user . '/files/');
$path = 'test_file_put_contents.txt';
/** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */
$storage = $this->getMockBuilder(Temporary::class)
- ->setMethods(['fopen'])
+ ->onlyMethods(['fopen'])
->getMock();
Filesystem::mount($storage, [], $this->user . '/');
@@ -1964,27 +2073,32 @@ class ViewTest extends \Test\TestCase {
/**
* Test locks for fopen with fclose at the end
*
- * @dataProvider basicOperationProviderForLocks
*
* @param string $operation operation name on the view
* @param array $operationArgs arguments for the operation
* @param string $path path of the locked item to check
*/
+ #[\PHPUnit\Framework\Attributes\DataProvider('basicOperationProviderForLocks')]
public function testLockBasicOperationUnlocksAfterException(
$operation,
$operationArgs,
- $path
- ) {
+ $path,
+ ): void {
if ($operation === 'touch') {
- $this->markTestSkipped("touch handles storage exceptions internally");
+ $this->markTestSkipped('touch handles storage exceptions internally');
}
$view = new View('/' . $this->user . '/files/');
/** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */
$storage = $this->getMockBuilder(Temporary::class)
- ->setMethods([$operation])
+ ->onlyMethods([$operation])
->getMock();
+ /* Pause trash to avoid the trashbin intercepting rmdir and unlink calls */
+ Server::get(ITrashManager::class)->pauseTrash();
+ /* Same thing with encryption wrapper */
+ Server::get(IStorageFactory::class)->removeStorageWrapper('oc_encryption');
+
Filesystem::mount($storage, [], $this->user . '/');
// work directly on disk because mkdir might be mocked
@@ -1997,7 +2111,7 @@ class ViewTest extends \Test\TestCase {
$storage->expects($this->once())
->method($operation)
->willReturnCallback(
- function () {
+ function (): void {
throw new \Exception('Simulated exception');
}
);
@@ -2011,9 +2125,12 @@ class ViewTest extends \Test\TestCase {
}
$this->assertTrue($thrown, 'Exception was rethrown');
$this->assertNull($this->getFileLockType($view, $path), 'File got unlocked after exception');
+
+ /* Resume trash to avoid side effects */
+ Server::get(ITrashManager::class)->resumeTrash();
}
- public function testLockBasicOperationUnlocksAfterLockException() {
+ public function testLockBasicOperationUnlocksAfterLockException(): void {
$view = new View('/' . $this->user . '/files/');
$storage = new Temporary([]);
@@ -2047,24 +2164,24 @@ class ViewTest extends \Test\TestCase {
/**
* Test locks for fopen with fclose at the end
*
- * @dataProvider basicOperationProviderForLocks
*
* @param string $operation operation name on the view
* @param array $operationArgs arguments for the operation
* @param string $path path of the locked item to check
* @param string $hookType hook type
*/
+ #[\PHPUnit\Framework\Attributes\DataProvider('basicOperationProviderForLocks')]
public function testLockBasicOperationUnlocksAfterCancelledHook(
$operation,
$operationArgs,
$path,
- $hookType
- ) {
+ $hookType,
+ ): void {
$view = new View('/' . $this->user . '/files/');
/** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */
$storage = $this->getMockBuilder(Temporary::class)
- ->setMethods([$operation])
+ ->onlyMethods([$operation])
->getMock();
Filesystem::mount($storage, [], $this->user . '/');
@@ -2082,7 +2199,7 @@ class ViewTest extends \Test\TestCase {
$this->assertNull($this->getFileLockType($view, $path), 'File got unlocked after exception');
}
- public function lockFileRenameOrCopyDataProvider() {
+ public static function lockFileRenameOrCopyDataProvider(): array {
return [
['rename', ILockingProvider::LOCK_EXCLUSIVE],
['copy', ILockingProvider::LOCK_SHARED],
@@ -2092,29 +2209,29 @@ class ViewTest extends \Test\TestCase {
/**
* Test locks for rename or copy operation
*
- * @dataProvider lockFileRenameOrCopyDataProvider
*
* @param string $operation operation to be done on the view
* @param int $expectedLockTypeSourceDuring expected lock type on source file during
- * the operation
+ * the operation
*/
- public function testLockFileRename($operation, $expectedLockTypeSourceDuring) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('lockFileRenameOrCopyDataProvider')]
+ public function testLockFileRename($operation, $expectedLockTypeSourceDuring): void {
$view = new View('/' . $this->user . '/files/');
/** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */
$storage = $this->getMockBuilder(Temporary::class)
- ->setMethods([$operation, 'getMetaData', 'filemtime'])
+ ->onlyMethods([$operation, 'getMetaData', 'filemtime'])
->getMock();
$storage->expects($this->any())
->method('getMetaData')
- ->will($this->returnValue([
+ ->willReturn([
'mtime' => 1885434487,
'etag' => '',
'mimetype' => 'text/plain',
'permissions' => Constants::PERMISSION_ALL,
'size' => 3
- ]));
+ ]);
$storage->expects($this->any())
->method('filemtime')
->willReturn(123456789);
@@ -2122,6 +2239,9 @@ class ViewTest extends \Test\TestCase {
$sourcePath = 'original.txt';
$targetPath = 'target.txt';
+ /* Disable encryption wrapper to avoid it intercepting mocked call */
+ Server::get(IStorageFactory::class)->removeStorageWrapper('oc_encryption');
+
Filesystem::mount($storage, [], $this->user . '/');
$storage->mkdir('files');
$view->file_put_contents($sourcePath, 'meh');
@@ -2162,19 +2282,22 @@ class ViewTest extends \Test\TestCase {
* We expect that we catch the exception, free the lock and re-throw it.
*
*/
- public function testLockFileCopyException() {
+ public function testLockFileCopyException(): void {
$this->expectException(\Exception::class);
$view = new View('/' . $this->user . '/files/');
/** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */
$storage = $this->getMockBuilder(Temporary::class)
- ->setMethods(['copy'])
+ ->onlyMethods(['copy'])
->getMock();
$sourcePath = 'original.txt';
$targetPath = 'target.txt';
+ /* Disable encryption wrapper to avoid it intercepting mocked call */
+ Server::get(IStorageFactory::class)->removeStorageWrapper('oc_encryption');
+
Filesystem::mount($storage, [], $this->user . '/');
$storage->mkdir('files');
$view->file_put_contents($sourcePath, 'meh');
@@ -2182,7 +2305,7 @@ class ViewTest extends \Test\TestCase {
$storage->expects($this->once())
->method('copy')
->willReturnCallback(
- function () {
+ function (): void {
throw new \Exception();
}
);
@@ -2205,7 +2328,7 @@ class ViewTest extends \Test\TestCase {
/**
* Test rename operation: unlock first path when second path was locked
*/
- public function testLockFileRenameUnlockOnException() {
+ public function testLockFileRenameUnlockOnException(): void {
self::loginAsUser('test');
$view = new View('/' . $this->user . '/files/');
@@ -2238,7 +2361,7 @@ class ViewTest extends \Test\TestCase {
/**
* Test rename operation: unlock first path when second path was locked
*/
- public function testGetOwner() {
+ public function testGetOwner(): void {
self::loginAsUser('test');
$view = new View('/test/files/');
@@ -2266,7 +2389,7 @@ class ViewTest extends \Test\TestCase {
$this->assertEquals('test', $folderInfo[0]->getOwner()->getUID());
}
- public function lockFileRenameOrCopyCrossStorageDataProvider() {
+ public static function lockFileRenameOrCopyCrossStorageDataProvider(): array {
return [
['rename', 'moveFromStorage', ILockingProvider::LOCK_EXCLUSIVE],
['copy', 'copyFromStorage', ILockingProvider::LOCK_SHARED],
@@ -2276,34 +2399,34 @@ class ViewTest extends \Test\TestCase {
/**
* Test locks for rename or copy operation cross-storage
*
- * @dataProvider lockFileRenameOrCopyCrossStorageDataProvider
*
* @param string $viewOperation operation to be done on the view
* @param string $storageOperation operation to be mocked on the storage
* @param int $expectedLockTypeSourceDuring expected lock type on source file during
- * the operation
+ * the operation
*/
- public function testLockFileRenameCrossStorage($viewOperation, $storageOperation, $expectedLockTypeSourceDuring) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('lockFileRenameOrCopyCrossStorageDataProvider')]
+ public function testLockFileRenameCrossStorage($viewOperation, $storageOperation, $expectedLockTypeSourceDuring): void {
$view = new View('/' . $this->user . '/files/');
/** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */
$storage = $this->getMockBuilder(Temporary::class)
- ->setMethods([$storageOperation])
+ ->onlyMethods([$storageOperation])
->getMock();
/** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage2 */
$storage2 = $this->getMockBuilder(Temporary::class)
- ->setMethods([$storageOperation, 'getMetaData', 'filemtime'])
+ ->onlyMethods([$storageOperation, 'getMetaData', 'filemtime'])
->getMock();
$storage2->expects($this->any())
->method('getMetaData')
- ->will($this->returnValue([
+ ->willReturn([
'mtime' => 1885434487,
'etag' => '',
'mimetype' => 'text/plain',
'permissions' => Constants::PERMISSION_ALL,
'size' => 3
- ]));
+ ]);
$storage2->expects($this->any())
->method('filemtime')
->willReturn(123456789);
@@ -2311,10 +2434,14 @@ class ViewTest extends \Test\TestCase {
$sourcePath = 'original.txt';
$targetPath = 'substorage/target.txt';
+ /* Disable encryption wrapper to avoid it intercepting mocked call */
+ Server::get(IStorageFactory::class)->removeStorageWrapper('oc_encryption');
+
Filesystem::mount($storage, [], $this->user . '/');
Filesystem::mount($storage2, [], $this->user . '/files/substorage');
$storage->mkdir('files');
$view->file_put_contents($sourcePath, 'meh');
+ $storage2->getUpdater()->update('');
$storage->expects($this->never())
->method($storageOperation);
@@ -2352,7 +2479,7 @@ class ViewTest extends \Test\TestCase {
/**
* Test locks when moving a mount point
*/
- public function testLockMoveMountPoint() {
+ public function testLockMoveMountPoint(): void {
self::loginAsUser('test');
[$mount] = $this->createTestMovableMountPoints([
@@ -2419,28 +2546,28 @@ class ViewTest extends \Test\TestCase {
* @param int $lockTypePre variable to receive lock type that was active in the pre-hook
* @param int $lockTypePost variable to receive lock type that was active in the post-hook
* @param bool $onMountPoint true to check the mount point instead of the
- * mounted storage
+ * mounted storage
*/
private function connectMockHooks($hookType, $view, $path, &$lockTypePre, &$lockTypePost, $onMountPoint = false) {
if ($hookType === null) {
return;
}
- $eventHandler = $this->getMockBuilder(\stdclass::class)
- ->setMethods(['preCallback', 'postCallback'])
+ $eventHandler = $this->getMockBuilder(TestEventHandler::class)
+ ->onlyMethods(['preCallback', 'postCallback'])
->getMock();
$eventHandler->expects($this->any())
->method('preCallback')
->willReturnCallback(
- function () use ($view, $path, $onMountPoint, &$lockTypePre) {
+ function () use ($view, $path, $onMountPoint, &$lockTypePre): void {
$lockTypePre = $this->getFileLockType($view, $path, $onMountPoint);
}
);
$eventHandler->expects($this->any())
->method('postCallback')
->willReturnCallback(
- function () use ($view, $path, $onMountPoint, &$lockTypePost) {
+ function () use ($view, $path, $onMountPoint, &$lockTypePost): void {
$lockTypePost = $this->getFileLockType($view, $path, $onMountPoint);
}
);
@@ -2467,7 +2594,7 @@ class ViewTest extends \Test\TestCase {
* @param View $view view
* @param string $path path
* @param bool $onMountPoint true to check the mount point instead of the
- * mounted storage
+ * mounted storage
*
* @return int lock type or null if file was not locked
*/
@@ -2481,7 +2608,7 @@ class ViewTest extends \Test\TestCase {
}
- public function testRemoveMoveableMountPoint() {
+ public function testRemoveMoveableMountPoint(): void {
$mountPoint = '/' . $this->user . '/files/mount/';
// Mock the mount point
@@ -2501,8 +2628,8 @@ class ViewTest extends \Test\TestCase {
Filesystem::getMountManager()->addMount($mount);
// Listen for events
- $eventHandler = $this->getMockBuilder(\stdclass::class)
- ->setMethods(['umount', 'post_umount'])
+ $eventHandler = $this->getMockBuilder(TestEventHandler::class)
+ ->onlyMethods(['umount', 'post_umount'])
->getMock();
$eventHandler->expects($this->once())
->method('umount')
@@ -2528,7 +2655,7 @@ class ViewTest extends \Test\TestCase {
$this->assertEquals('foo', $view->rmdir('mount'));
}
- public function mimeFilterProvider() {
+ public static function mimeFilterProvider(): array {
return [
[null, ['test1.txt', 'test2.txt', 'test3.md', 'test4.png']],
['text/plain', ['test1.txt', 'test2.txt']],
@@ -2540,9 +2667,9 @@ class ViewTest extends \Test\TestCase {
/**
* @param string $filter
* @param string[] $expected
- * @dataProvider mimeFilterProvider
*/
- public function testGetDirectoryContentMimeFilter($filter, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('mimeFilterProvider')]
+ public function testGetDirectoryContentMimeFilter($filter, $expected): void {
$storage1 = new Temporary();
$root = self::getUniqueID('/');
Filesystem::mount($storage1, [], $root . '/');
@@ -2563,7 +2690,7 @@ class ViewTest extends \Test\TestCase {
$this->assertEquals($expected, $files);
}
- public function testFilePutContentsClearsChecksum() {
+ public function testFilePutContentsClearsChecksum(): void {
$storage = new Temporary([]);
$scanner = $storage->getScanner();
$storage->file_put_contents('foo.txt', 'bar');
@@ -2584,7 +2711,7 @@ class ViewTest extends \Test\TestCase {
$this->assertEquals('', $data->getChecksum());
}
- public function testDeleteGhostFile() {
+ public function testDeleteGhostFile(): void {
$storage = new Temporary([]);
$scanner = $storage->getScanner();
$cache = $storage->getCache();
@@ -2607,7 +2734,7 @@ class ViewTest extends \Test\TestCase {
$this->assertEquals(0, $newInfo->getSize());
}
- public function testDeleteGhostFolder() {
+ public function testDeleteGhostFolder(): void {
$storage = new Temporary([]);
$scanner = $storage->getScanner();
$cache = $storage->getCache();
@@ -2633,10 +2760,10 @@ class ViewTest extends \Test\TestCase {
$this->assertEquals(0, $newInfo->getSize());
}
- public function testCreateParentDirectories() {
+ public function testCreateParentDirectories(): void {
$view = $this->getMockBuilder(View::class)
->disableOriginalConstructor()
- ->setMethods([
+ ->onlyMethods([
'is_file',
'file_exists',
'mkdir',
@@ -2645,37 +2772,34 @@ class ViewTest extends \Test\TestCase {
$view->expects($this->exactly(3))
->method('is_file')
- ->withConsecutive(
- ['/new'],
- ['/new/folder'],
- ['/new/folder/structure'],
- )
- ->willReturn(false);
+ ->willReturnMap([
+ ['/new', false],
+ ['/new/folder', false],
+ ['/new/folder/structure', false],
+ ]);
$view->expects($this->exactly(3))
->method('file_exists')
- ->withConsecutive(
- ['/new'],
- ['/new/folder'],
- ['/new/folder/structure'],
- )->willReturnOnConsecutiveCalls(
- true,
- false,
- false,
- );
+ ->willReturnMap([
+ ['/new', true],
+ ['/new/folder', false],
+ ['/new/folder/structure', false],
+ ]);
+
+ $calls = ['/new/folder', '/new/folder/structure'];
$view->expects($this->exactly(2))
->method('mkdir')
- ->withConsecutive(
- ['/new/folder'],
- ['/new/folder/structure'],
- );
+ ->willReturnCallback(function ($dir) use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, $dir);
+ });
$this->assertTrue(self::invokePrivate($view, 'createParentDirectories', ['/new/folder/structure']));
}
- public function testCreateParentDirectoriesWithExistingFile() {
+ public function testCreateParentDirectoriesWithExistingFile(): void {
$view = $this->getMockBuilder(View::class)
->disableOriginalConstructor()
- ->setMethods([
+ ->onlyMethods([
'is_file',
'file_exists',
'mkdir',
@@ -2690,7 +2814,7 @@ class ViewTest extends \Test\TestCase {
$this->assertFalse(self::invokePrivate($view, 'createParentDirectories', ['/file.txt/folder/structure']));
}
- public function testCacheExtension() {
+ public function testCacheExtension(): void {
$storage = new Temporary([]);
$scanner = $storage->getScanner();
$storage->file_put_contents('foo.txt', 'bar');
@@ -2710,7 +2834,7 @@ class ViewTest extends \Test\TestCase {
$this->assertEquals(0, $info->getCreationTime());
}
- public function testFopenGone() {
+ public function testFopenGone(): void {
$storage = new Temporary([]);
$scanner = $storage->getScanner();
$storage->file_put_contents('foo.txt', 'bar');
@@ -2728,4 +2852,43 @@ class ViewTest extends \Test\TestCase {
$this->assertFalse($cache->inCache('foo.txt'));
}
+
+ public function testMountpointParentsCreated(): void {
+ $storage1 = $this->getTestStorage();
+ Filesystem::mount($storage1, [], '/');
+
+ $storage2 = $this->getTestStorage();
+ Filesystem::mount($storage2, [], '/A/B/C');
+
+ $rootView = new View('');
+
+ $folderData = $rootView->getDirectoryContent('/');
+ $this->assertCount(4, $folderData);
+ $this->assertEquals('folder', $folderData[0]['name']);
+ $this->assertEquals('foo.png', $folderData[1]['name']);
+ $this->assertEquals('foo.txt', $folderData[2]['name']);
+ $this->assertEquals('A', $folderData[3]['name']);
+
+ $folderData = $rootView->getDirectoryContent('/A');
+ $this->assertCount(1, $folderData);
+ $this->assertEquals('B', $folderData[0]['name']);
+
+ $folderData = $rootView->getDirectoryContent('/A/B');
+ $this->assertCount(1, $folderData);
+ $this->assertEquals('C', $folderData[0]['name']);
+
+ $folderData = $rootView->getDirectoryContent('/A/B/C');
+ $this->assertCount(3, $folderData);
+ $this->assertEquals('folder', $folderData[0]['name']);
+ $this->assertEquals('foo.png', $folderData[1]['name']);
+ $this->assertEquals('foo.txt', $folderData[2]['name']);
+ }
+
+ public function testCopyPreservesContent() {
+ $viewUser1 = new View('/' . 'userId' . '/files');
+ $viewUser1->mkdir('');
+ $viewUser1->file_put_contents('foo.txt', 'foo');
+ $viewUser1->copy('foo.txt', 'bar.txt');
+ $this->assertEquals('foo', $viewUser1->file_get_contents('bar.txt'));
+ }
}