diff --git a/psalm.xml b/psalm.xml index 20f52ff37..cc9a641fd 100644 --- a/psalm.xml +++ b/psalm.xml @@ -18,37 +18,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - @@ -65,13 +37,17 @@ + + + + @@ -81,6 +57,24 @@ + + + + + + + + + + + + + + + + + + @@ -100,19 +94,31 @@ + + + + + + + + + + + + + + + - - - - + diff --git a/tests/ACL/ACLCacheWrapperTest.php b/tests/ACL/ACLCacheWrapperTest.php index 562700196..f1525af69 100644 --- a/tests/ACL/ACLCacheWrapperTest.php +++ b/tests/ACL/ACLCacheWrapperTest.php @@ -13,17 +13,16 @@ use OCA\GroupFolders\ACL\ACLManager; use OCP\Constants; use OCP\Files\Cache\ICache; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; /** * @group DB */ class ACLCacheWrapperTest extends TestCase { - /** @var ACLManager|\PHPUnit_Framework_MockObject_MockObject */ - private $aclManager; - /** @var ICache|\PHPUnit_Framework_MockObject_MockObject */ - private $source; - private ?ACLCacheWrapper $cache = null; + private ACLManager&MockObject $aclManager; + private ICache&MockObject $source; + private ACLCacheWrapper $cache; private array $aclPermissions = []; protected function setUp(): void { diff --git a/tests/ACL/ACLManagerTest.php b/tests/ACL/ACLManagerTest.php index 188d13fba..9b6d5deec 100644 --- a/tests/ACL/ACLManagerTest.php +++ b/tests/ACL/ACLManagerTest.php @@ -17,17 +17,18 @@ use OCP\Files\IRootFolder; use OCP\Files\Mount\IMountPoint; use OCP\IUser; +use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; use Test\TestCase; class ACLManagerTest extends TestCase { - private RuleManager $ruleManager; - private TrashManager $trashManager; - private LoggerInterface $logger; - private IUser $user; + private RuleManager&MockObject $ruleManager; + private TrashManager&MockObject $trashManager; + private LoggerInterface&MockObject $logger; + private IUser&MockObject $user; private ACLManager $aclManager; - private IUserMapping $dummyMapping; - /** @var Rule[] */ + private IUserMapping&MockObject $dummyMapping; + /** @var array> */ private array $rules = []; protected function setUp(): void { @@ -50,7 +51,7 @@ protected function setUp(): void { }); } - private function createMapping(string $id): IUserMapping { + private function createMapping(string $id): IUserMapping&MockObject { $mapping = $this->createMock(IUserMapping::class); $mapping->method('getType')->willReturn('dummy'); $mapping->method('getId')->willReturn($id); @@ -67,7 +68,7 @@ private function getAclManager(bool $perUserMerge = false): ACLManager { $rootFolder->method('getMountPoint') ->willReturn($rootMountPoint); - return new ACLManager($this->ruleManager, $this->trashManager, $this->logger, $this->user, fn () => $rootFolder, null, $perUserMerge); + return new ACLManager($this->ruleManager, $this->trashManager, $this->logger, $this->user, fn (): IRootFolder&MockObject => $rootFolder, null, $perUserMerge); } public function testGetACLPermissionsForPathNoRules(): void { diff --git a/tests/ACL/ACLScannerTest.php b/tests/ACL/ACLScannerTest.php index 222b07bb8..c6f72b523 100644 --- a/tests/ACL/ACLScannerTest.php +++ b/tests/ACL/ACLScannerTest.php @@ -11,18 +11,19 @@ use OCA\GroupFolders\ACL\ACLManager; use OCA\GroupFolders\ACL\ACLStorageWrapper; use OCP\Constants; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; /** * @group DB */ class ACLScannerTest extends TestCase { - private function getAclManager(array $rules): ACLManager { + private function getAclManager(array $rules): ACLManager&MockObject { $manager = $this->getMockBuilder(ACLManager::class) ->disableOriginalConstructor() ->getMock(); $manager->method('getACLPermissionsForPath') - ->willReturnCallback(fn ($path) => $rules[$path] ?? Constants::PERMISSION_ALL); + ->willReturnCallback(fn (string $path) => $rules[$path] ?? Constants::PERMISSION_ALL); return $manager; } diff --git a/tests/ACL/ACLStorageWrapperTest.php b/tests/ACL/ACLStorageWrapperTest.php index 7b2f993ff..6eabafd46 100644 --- a/tests/ACL/ACLStorageWrapperTest.php +++ b/tests/ACL/ACLStorageWrapperTest.php @@ -12,13 +12,14 @@ use OCA\GroupFolders\ACL\ACLManager; use OCA\GroupFolders\ACL\ACLStorageWrapper; use OCP\Constants; +use OCP\Files\Storage\IStorage; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class ACLStorageWrapperTest extends TestCase { - /** @var ACLManager|\PHPUnit_Framework_MockObject_MockObject */ - private $aclManager; - private ?Temporary $source = null; - private ?ACLStorageWrapper $storage = null; + private ACLManager&MockObject $aclManager; + private IStorage $source; + private ACLStorageWrapper $storage; private array $aclPermissions = []; protected function setUp(): void { diff --git a/tests/ACL/RuleManagerTest.php b/tests/ACL/RuleManagerTest.php index 0d50f91b3..6db0cc766 100644 --- a/tests/ACL/RuleManagerTest.php +++ b/tests/ACL/RuleManagerTest.php @@ -14,22 +14,21 @@ use OCA\GroupFolders\ACL\UserMapping\IUserMappingManager; use OCA\GroupFolders\ACL\UserMapping\UserMapping; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IDBConnection; use OCP\IUser; use OCP\Log\Audit\CriticalActionPerformedEvent; +use OCP\Server; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; /** * @group DB */ class RuleManagerTest extends TestCase { - /** @var \PHPUnit_Framework_MockObject_MockObject | IUserMappingManager */ - private $userMappingManager; - private ?RuleManager $ruleManager = null; - /** @var \PHPUnit_Framework_MockObject_MockObject | IUser */ - private $user; - - /** @var \PHPUnit_Framework_MockObject_MockObject | IEventDispatcher */ - private $eventDispatcher; + private IUserMappingManager&MockObject $userMappingManager; + private RuleManager $ruleManager; + private IUser&MockObject $user; + private IEventDispatcher&MockObject $eventDispatcher; protected function setUp(): void { parent::setUp(); @@ -41,65 +40,62 @@ protected function setUp(): void { $this->userMappingManager = $this->createMock(IUserMappingManager::class); $this->userMappingManager->expects($this->any()) ->method('mappingFromId') - ->willReturnCallback(function ($type, $id): UserMapping { - if ($type === 'user') { - return new UserMapping($type, $id, 'The User'); - } else { - return new UserMapping($type, $id); - } - }); + ->willReturnCallback(fn (string $type, string $id): UserMapping => new UserMapping($type, $id)); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); - $this->ruleManager = new RuleManager(\OC::$server->getDatabaseConnection(), $this->userMappingManager, $this->eventDispatcher); + $this->ruleManager = new RuleManager(Server::get(IDBConnection::class), $this->userMappingManager, $this->eventDispatcher); } public function testGetSetRule(): void { - $mapping = new UserMapping('user', '1', 'The User'); + $mapping = new UserMapping('user', '1'); $this->userMappingManager->expects($this->any()) ->method('getMappingsForUser') ->with($this->user) ->willReturn([$mapping]); + $parameters = null; $this->eventDispatcher->expects($this->any()) ->method('dispatchTyped') - ->withConsecutive( - [$this->callback(fn (CriticalActionPerformedEvent $event): bool => $event->getParameters() === [ - 'permissions' => 0b00001001, - 'mask' => 0b00001111, - 'fileId' => 10, - 'user' => 'The User (1)', - ])], - [$this->callback(fn (CriticalActionPerformedEvent $event): bool => $event->getParameters() === [ - 'permissions' => 0b00001000, - 'mask' => 0b00001111, - 'fileId' => 10, - 'user' => 'The User (1)', - ])], - [$this->callback(fn (CriticalActionPerformedEvent $event): bool => $event->getParameters() === [ - 'fileId' => 10, - 'user' => 'The User (1)', - ])], - ); + ->willReturnCallback(function (CriticalActionPerformedEvent $event) use (&$parameters): bool { + $parameters = $event->getParameters(); + return true; + }); $rule = new Rule($mapping, 10, 0b00001111, 0b00001001); $this->ruleManager->saveRule($rule); + $this->assertEquals([ + 'permissions' => 0b00001001, + 'mask' => 0b00001111, + 'fileId' => 10, + 'user' => '1 (1)', + ], $parameters); $result = $this->ruleManager->getRulesForFilesById($this->user, [10]); $this->assertEquals([10 => [$rule]], $result); $updatedRule = new Rule($mapping, 10, 0b00001111, 0b00001000); $this->ruleManager->saveRule($updatedRule); + $this->assertEquals([ + 'permissions' => 0b00001000, + 'mask' => 0b00001111, + 'fileId' => 10, + 'user' => '1 (1)', + ], $parameters); $result = $this->ruleManager->getRulesForFilesById($this->user, [10]); $this->assertEquals([10 => [$updatedRule]], $result); // cleanup $this->ruleManager->deleteRule($rule); + $this->assertEquals([ + 'fileId' => 10, + 'user' => '1 (1)', + ], $parameters); } public function testGetMultiple(): void { - $mapping1 = new UserMapping('test', '1'); - $mapping2 = new UserMapping('test', '2'); + $mapping1 = new UserMapping('user', '1'); + $mapping2 = new UserMapping('user', '2'); $this->userMappingManager->expects($this->any()) ->method('getMappingsForUser') ->with($this->user) @@ -134,7 +130,7 @@ public function testGetByPath(): void { $id2 = (int)$cache->getId('foo/bar'); $storageId = $cache->getNumericStorageId(); - $mapping = new UserMapping('test', '1'); + $mapping = new UserMapping('user', '1'); $this->userMappingManager->expects($this->any()) ->method('getMappingsForUser') ->with($this->user) @@ -174,7 +170,7 @@ public function testGetByPathMore(): void { $id1 = (int)$cache->getId('foo'); $storageId = $cache->getNumericStorageId(); - $mapping = new UserMapping('test', '1'); + $mapping = new UserMapping('user', '1'); $this->userMappingManager->expects($this->any()) ->method('getMappingsForUser') ->with($this->user) @@ -211,7 +207,7 @@ public function testGetByParent(): void { $id3 = (int)$cache->getId('foo/asd'); $storageId = $cache->getNumericStorageId(); - $mapping = new UserMapping('test', '1'); + $mapping = new UserMapping('user', '1'); $this->userMappingManager->expects($this->any()) ->method('getMappingsForUser') ->with($this->user) diff --git a/tests/ACL/RuleTest.php b/tests/ACL/RuleTest.php index fe2f146d0..d932def00 100644 --- a/tests/ACL/RuleTest.php +++ b/tests/ACL/RuleTest.php @@ -13,7 +13,7 @@ use Test\TestCase; class RuleTest extends TestCase { - public function permissionsProvider() { + public function permissionsProvider(): array { return [ [0b00000000, 0b00000000, 0b00000000, 0b00000000], [0b10101010, 0b00000000, 0b11110000, 0b10101010], //empty mask should have no effect @@ -26,12 +26,12 @@ public function permissionsProvider() { /** * @dataProvider permissionsProvider */ - public function testApplyPermissions($input, $mask, $permissions, $expected): void { + public function testApplyPermissions(int $input, int $mask, int $permissions, int $expected): void { $rule = new Rule($this->createMock(IUserMapping::class), 0, $mask, $permissions); $this->assertEquals($expected, $rule->applyPermissions($input)); } - public function mergeRulesProvider() { + public function mergeRulesProvider(): array { return [ [[ [0b00001111, 0b00000011], @@ -56,7 +56,7 @@ public function mergeRulesProvider() { /** * @dataProvider mergeRulesProvider */ - public function testMergeRules($inputs, $expectedMask, $expectedPermissions): void { + public function testMergeRules(array $inputs, int $expectedMask, int $expectedPermissions): void { $inputRules = array_map(fn (array $input): Rule => new Rule($this->createMock(IUserMapping::class), 0, $input[0], $input[1]), $inputs); $result = Rule::mergeRules($inputRules); diff --git a/tests/Folder/FolderManagerTest.php b/tests/Folder/FolderManagerTest.php index 4cd515e1f..94ff9f377 100644 --- a/tests/Folder/FolderManagerTest.php +++ b/tests/Folder/FolderManagerTest.php @@ -14,6 +14,8 @@ use OCP\IDBConnection; use OCP\IGroupManager; use OCP\IUser; +use OCP\Server; +use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; use Test\TestCase; @@ -22,11 +24,11 @@ */ class FolderManagerTest extends TestCase { private FolderManager $manager; - private IGroupManager $groupManager; - private IMimeTypeLoader $mimeLoader; - private LoggerInterface $logger; - private IEventDispatcher $eventDispatcher; - private IConfig $config; + private IGroupManager&MockObject $groupManager; + private IMimeTypeLoader&MockObject $mimeLoader; + private LoggerInterface&MockObject $logger; + private IEventDispatcher&MockObject $eventDispatcher; + private IConfig&MockObject $config; protected function setUp(): void { parent::setUp(); @@ -41,7 +43,7 @@ protected function setUp(): void { ->with('groupfolders.quota.default', -3) ->willReturn(-3); $this->manager = new FolderManager( - \OC::$server->getDatabaseConnection(), + Server::get(IDBConnection::class), $this->groupManager, $this->mimeLoader, $this->logger, @@ -52,11 +54,11 @@ protected function setUp(): void { } private function clean(): void { - $query = \OC::$server->getDatabaseConnection()->getQueryBuilder(); - $query->delete('group_folders')->execute(); + $query = Server::get(IDBConnection::class)->getQueryBuilder(); + $query->delete('group_folders')->executeStatement(); - $query = \OC::$server->getDatabaseConnection()->getQueryBuilder(); - $query->delete('group_folders_groups')->execute(); + $query = Server::get(IDBConnection::class)->getQueryBuilder(); + $query->delete('group_folders_groups')->executeStatement(); } private function assertHasFolders(array $folders): void { @@ -291,9 +293,8 @@ public function testGetFoldersForGroups(): void { /** * @param string[] $groups - * @return \PHPUnit_Framework_MockObject_MockObject|IUser */ - protected function getUser($groups = []) { + protected function getUser($groups = []): IUser&MockObject { $id = uniqid(); $user = $this->createMock(IUser::class); $this->groupManager->expects($this->any()) @@ -313,10 +314,9 @@ public function testGetFoldersForUserEmpty(): void { public function testGetFoldersForUserSimple(): void { $db = $this->createMock(IDBConnection::class); - /** @var FolderManager|\PHPUnit_Framework_MockObject_MockObject $manager */ $manager = $this->getMockBuilder(FolderManager::class) ->setConstructorArgs([$db, $this->groupManager, $this->mimeLoader, $this->logger, $this->eventDispatcher, $this->config]) - ->setMethods(['getFoldersForGroups']) + ->onlyMethods(['getFoldersForGroups']) ->getMock(); $folder = [ @@ -336,10 +336,9 @@ public function testGetFoldersForUserSimple(): void { public function testGetFoldersForUserMerge(): void { $db = $this->createMock(IDBConnection::class); - /** @var FolderManager|\PHPUnit_Framework_MockObject_MockObject $manager */ $manager = $this->getMockBuilder(FolderManager::class) ->setConstructorArgs([$db, $this->groupManager, $this->mimeLoader, $this->logger, $this->eventDispatcher, $this->config]) - ->setMethods(['getFoldersForGroups']) + ->onlyMethods(['getFoldersForGroups']) ->getMock(); $folder1 = [ @@ -372,10 +371,9 @@ public function testGetFoldersForUserMerge(): void { public function testGetFolderPermissionsForUserMerge(): void { $db = $this->createMock(IDBConnection::class); - /** @var FolderManager|\PHPUnit_Framework_MockObject_MockObject $manager */ $manager = $this->getMockBuilder(FolderManager::class) ->setConstructorArgs([$db, $this->groupManager, $this->mimeLoader, $this->logger, $this->eventDispatcher, $this->config]) - ->setMethods(['getFoldersForGroups']) + ->onlyMethods(['getFoldersForGroups']) ->getMock(); $folder1 = [ diff --git a/tests/stubs/oc_files_setupmanager.php b/tests/stubs/oc_files_setupmanager.php new file mode 100644 index 000000000..83c40ff76 --- /dev/null +++ b/tests/stubs/oc_files_setupmanager.php @@ -0,0 +1,97 @@ + an array of user ids + */ + public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0): array + { + } + + public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array + { + } + + /** + * get the number of all users matching the search string in a group + * @param string $gid + * @param string $search + * @return int + */ + public function countUsersInGroup(string $gid, string $search = ''): int + { + } + + /** + * get the number of disabled users in a group + * + * @param string $search + * + * @return int + */ + public function countDisabledInGroup(string $gid): int + { + } + + public function getDisplayName(string $gid): string + { + } + + public function getGroupDetails(string $gid): array + { + } + + /** + * {@inheritdoc} + */ + public function getGroupsDetails(array $gids): array + { + } + + public function setDisplayName(string $gid, string $displayName): bool + { + } + + /** + * Backend name to be shown in group management + * @return string the name of the backend to be shown + * @since 21.0.0 + */ + public function getBackendName(): string + { + } +} diff --git a/tests/stubs/oc_server.php b/tests/stubs/oc_server.php index 08927f9b9..f3f822823 100644 --- a/tests/stubs/oc_server.php +++ b/tests/stubs/oc_server.php @@ -177,7 +177,6 @@ use OCP\IGroupManager; use OCP\IInitialStateService; use OCP\IL10N; -use OCP\ILogger; use OCP\INavigationManager; use OCP\IPhoneNumberUtil; use OCP\IPreview; @@ -204,6 +203,7 @@ use OCP\Profiler\IProfiler; use OCP\Remote\Api\IApiFactory; use OCP\Remote\IInstanceFactory; +use OCP\RichObjectStrings\IRichTextFormatter; use OCP\RichObjectStrings\IValidator; use OCP\Route\IRouter; use OCP\Security\Bruteforce\IThrottler; @@ -594,16 +594,6 @@ public function getActivityManager() */ public function getJobList() { - } - - /** - * Returns a logger instance - * - * @return ILogger - * @deprecated 20.0.0 - */ - public function getLogger() - { } /** diff --git a/tests/stubs/test_testcase.php b/tests/stubs/test_testcase.php new file mode 100644 index 000000000..f85a013f9 --- /dev/null +++ b/tests/stubs/test_testcase.php @@ -0,0 +1,255 @@ +=')) { + trait OnNotSuccessfulTestTrait { + protected function onNotSuccessfulTest(\Throwable $t): never { + $this->restoreAllServices(); + + // restore database connection + if (!$this->IsDatabaseAccessAllowed()) { + \OC::$server->registerService(IDBConnection::class, function () { + return self::$realDatabase; + }); + } + + parent::onNotSuccessfulTest($t); + } + } +} else { + trait OnNotSuccessfulTestTrait { + protected function onNotSuccessfulTest(\Throwable $t): void { + $this->restoreAllServices(); + + // restore database connection + if (!$this->IsDatabaseAccessAllowed()) { + \OC::$server->registerService(IDBConnection::class, function () { + return self::$realDatabase; + }); + } + + parent::onNotSuccessfulTest($t); + } + } +} + +abstract class TestCase extends \PHPUnit\Framework\TestCase { + /** @var IDBConnection */ + protected static $realDatabase = null; + + /** @var array */ + protected $services = []; + + use OnNotSuccessfulTestTrait; + + /** + * @param string $name + * @param mixed $newService + * @return bool + */ + public function overwriteService(string $name, $newService): bool + { + } + + /** + * @param string $name + * @return bool + */ + public function restoreService(string $name): bool + { + } + + public function restoreAllServices() + { + } + + protected function getTestTraits() + { + } + + protected function setUp(): void + { + } + + protected function tearDown(): void + { + } + + /** + * Allows us to test private methods/properties + * + * @param $object + * @param $methodName + * @param array $parameters + * @return mixed + */ + protected static function invokePrivate($object, $methodName, array $parameters = []) + { + } + + /** + * Returns a unique identifier as uniqid() is not reliable sometimes + * + * @param string $prefix + * @param int $length + * @return string + */ + protected static function getUniqueID($prefix = '', $length = 13) + { + } + + public static function tearDownAfterClass(): void + { + } + + /** + * Remove all entries from the share table + * + * @param IQueryBuilder $queryBuilder + */ + protected static function tearDownAfterClassCleanShares(IQueryBuilder $queryBuilder) + { + } + + /** + * Remove all entries from the storages table + * + * @param IQueryBuilder $queryBuilder + */ + protected static function tearDownAfterClassCleanStorages(IQueryBuilder $queryBuilder) + { + } + + /** + * Remove all entries from the filecache table + * + * @param IQueryBuilder $queryBuilder + */ + protected static function tearDownAfterClassCleanFileCache(IQueryBuilder $queryBuilder) + { + } + + /** + * Remove all unused files from the data dir + * + * @param string $dataDir + */ + protected static function tearDownAfterClassCleanStrayDataFiles($dataDir) + { + } + + /** + * Recursive delete files and folders from a given directory + * + * @param string $dir + */ + protected static function tearDownAfterClassCleanStrayDataUnlinkDir($dir) + { + } + + /** + * Clean up the list of hooks + */ + protected static function tearDownAfterClassCleanStrayHooks() + { + } + + /** + * Clean up the list of locks + */ + protected static function tearDownAfterClassCleanStrayLocks() + { + } + + /** + * Login and setup FS as a given user, + * sets the given user as the current user. + * + * @param string $user user id or empty for a generic FS + */ + protected static function loginAsUser($user = '') + { + } + + /** + * Logout the current user and tear down the filesystem. + */ + protected static function logout() + { + } + + /** + * Run all commands pushed to the bus + */ + protected function runCommands() + { + } + + /** + * Check if the given path is locked with a given type + * + * @param \OC\Files\View $view view + * @param string $path path to check + * @param int $type lock type + * @param bool $onMountPoint true to check the mount point instead of the + * mounted storage + * + * @return boolean true if the file is locked with the + * given type, false otherwise + */ + protected function isFileLocked($view, $path, $type, $onMountPoint = false) + { + } + + protected function getGroupAnnotations(): array + { + } + + protected function IsDatabaseAccessAllowed() + { + } + + /** + * @param string $expectedHtml + * @param string $template + * @param array $vars + */ + protected function assertTemplate($expectedHtml, $template, $vars = []) + { + } + + /** + * @param string $expectedHtml + * @param string $actualHtml + * @param string $message + */ + protected function assertHtmlStringEqualsHtmlString($expectedHtml, $actualHtml, $message = '') + { + } +} diff --git a/tests/stubs/test_traits_usertrait.php b/tests/stubs/test_traits_usertrait.php new file mode 100644 index 000000000..365813948 --- /dev/null +++ b/tests/stubs/test_traits_usertrait.php @@ -0,0 +1,45 @@ +uid = $uid; + } + + public function getUID(): string { + return $this->uid; + } +} + +/** + * Allow creating users in a temporary backend + */ +trait UserTrait { + /** + * @var \Test\Util\User\Dummy|\OCP\UserInterface + */ + protected $userBackend; + + protected function createUser($name, $password): IUser + { + } + + protected function setUpUserTrait() + { + } + + protected function tearDownUserTrait() + { + } +}