diff options
Diffstat (limited to 'tests/Core')
71 files changed, 2773 insertions, 2346 deletions
diff --git a/tests/Core/Command/Apps/AppsDisableTest.php b/tests/Core/Command/Apps/AppsDisableTest.php index 2b276948b04..117af958054 100644 --- a/tests/Core/Command/Apps/AppsDisableTest.php +++ b/tests/Core/Command/Apps/AppsDisableTest.php @@ -2,28 +2,15 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2019, Daniel Kesselberg (mail@danielkesselberg.de) - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Command\Config; use OC\Core\Command\App\Disable; +use OCP\App\IAppManager; +use OCP\Server; use Symfony\Component\Console\Tester\CommandTester; use Test\TestCase; @@ -40,22 +27,22 @@ class AppsDisableTest extends TestCase { parent::setUp(); $command = new Disable( - \OC::$server->getAppManager() + Server::get(IAppManager::class) ); $this->commandTester = new CommandTester($command); - \OC::$server->getAppManager()->enableApp('admin_audit'); - \OC::$server->getAppManager()->enableApp('comments'); + Server::get(IAppManager::class)->enableApp('admin_audit'); + Server::get(IAppManager::class)->enableApp('comments'); } /** - * @dataProvider dataCommandInput * @param $appId * @param $groups * @param $statusCode * @param $pattern */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataCommandInput')] public function testCommandInput($appId, $statusCode, $pattern): void { $input = ['app-id' => $appId]; @@ -65,7 +52,7 @@ class AppsDisableTest extends TestCase { $this->assertSame($statusCode, $this->commandTester->getStatusCode()); } - public function dataCommandInput(): array { + public static function dataCommandInput(): array { return [ [['admin_audit'], 0, 'admin_audit ([\d\.]*) disabled'], [['comments'], 0, 'comments ([\d\.]*) disabled'], diff --git a/tests/Core/Command/Apps/AppsEnableTest.php b/tests/Core/Command/Apps/AppsEnableTest.php index 6e577464103..604c670ae15 100644 --- a/tests/Core/Command/Apps/AppsEnableTest.php +++ b/tests/Core/Command/Apps/AppsEnableTest.php @@ -2,28 +2,17 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2019, Daniel Kesselberg (mail@danielkesselberg.de) - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Command\Config; use OC\Core\Command\App\Enable; +use OC\Installer; +use OCP\App\IAppManager; +use OCP\IGroupManager; +use OCP\Server; use Symfony\Component\Console\Tester\CommandTester; use Test\TestCase; @@ -40,23 +29,24 @@ class AppsEnableTest extends TestCase { parent::setUp(); $command = new Enable( - \OC::$server->getAppManager(), - \OC::$server->getGroupManager() + Server::get(IAppManager::class), + Server::get(IGroupManager::class), + Server::get(Installer::class), ); $this->commandTester = new CommandTester($command); - \OC::$server->getAppManager()->disableApp('admin_audit'); - \OC::$server->getAppManager()->disableApp('comments'); + Server::get(IAppManager::class)->disableApp('admin_audit'); + Server::get(IAppManager::class)->disableApp('comments'); } /** - * @dataProvider dataCommandInput * @param $appId * @param $groups * @param $statusCode * @param $pattern */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataCommandInput')] public function testCommandInput($appId, $groups, $statusCode, $pattern): void { $input = ['app-id' => $appId]; @@ -70,7 +60,7 @@ class AppsEnableTest extends TestCase { $this->assertSame($statusCode, $this->commandTester->getStatusCode()); } - public function dataCommandInput(): array { + public static function dataCommandInput(): array { return [ [['admin_audit'], null, 0, 'admin_audit ([\d\.]*) enabled'], [['comments'], null, 0, 'comments ([\d\.]*) enabled'], diff --git a/tests/Core/Command/Config/App/DeleteConfigTest.php b/tests/Core/Command/Config/App/DeleteConfigTest.php index 2c9482b57f6..9e43f389214 100644 --- a/tests/Core/Command/Config/App/DeleteConfigTest.php +++ b/tests/Core/Command/Config/App/DeleteConfigTest.php @@ -1,58 +1,43 @@ <?php + +declare(strict_types=1); /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Config\App; +use OC\Config\ConfigManager; use OC\Core\Command\Config\App\DeleteConfig; -use OCP\IConfig; +use OCP\IAppConfig; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; class DeleteConfigTest extends TestCase { - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ - protected $config; - - /** @var \PHPUnit\Framework\MockObject\MockObject */ - protected $consoleInput; - /** @var \PHPUnit\Framework\MockObject\MockObject */ - protected $consoleOutput; - - /** @var \Symfony\Component\Console\Command\Command */ - protected $command; + protected IAppConfig&MockObject $appConfig; + protected ConfigManager&MockObject $configManager; + protected InputInterface&MockObject $consoleInput; + protected OutputInterface&MockObject $consoleOutput; + protected Command $command; protected function setUp(): void { parent::setUp(); - $this->config = $this->getMockBuilder(IConfig::class) - ->disableOriginalConstructor() - ->getMock(); - $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); - $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); + $this->appConfig = $this->createMock(IAppConfig::class); + $this->configManager = $this->createMock(ConfigManager::class); + $this->consoleInput = $this->createMock(InputInterface::class); + $this->consoleOutput = $this->createMock(OutputInterface::class); - $this->command = new DeleteConfig($this->config); + $this->command = new DeleteConfig($this->appConfig, $this->configManager); } - public function deleteData() { + public static function dataDelete(): array { return [ [ 'name', @@ -85,23 +70,15 @@ class DeleteConfigTest extends TestCase { ]; } - /** - * @dataProvider deleteData - * - * @param string $configName - * @param bool $configExists - * @param bool $checkIfExists - * @param int $expectedReturn - * @param string $expectedMessage - */ - public function testDelete($configName, $configExists, $checkIfExists, $expectedReturn, $expectedMessage) { - $this->config->expects(($checkIfExists) ? $this->once() : $this->never()) - ->method('getAppKeys') + #[\PHPUnit\Framework\Attributes\DataProvider('dataDelete')] + public function testDelete(string $configName, bool $configExists, bool $checkIfExists, int $expectedReturn, string $expectedMessage): void { + $this->appConfig->expects(($checkIfExists) ? $this->once() : $this->never()) + ->method('getKeys') ->with('app-name') ->willReturn($configExists ? [$configName] : []); - $this->config->expects(($expectedReturn === 0) ? $this->once() : $this->never()) - ->method('deleteAppValue') + $this->appConfig->expects(($expectedReturn === 0) ? $this->once() : $this->never()) + ->method('deleteKey') ->with('app-name', $configName); $this->consoleInput->expects($this->exactly(2)) @@ -110,15 +87,13 @@ class DeleteConfigTest extends TestCase { ['app', 'app-name'], ['name', $configName], ]); - $this->consoleInput->expects($this->any()) - ->method('hasParameterOption') + $this->consoleInput->method('hasParameterOption') ->with('--error-if-not-exists') ->willReturn($checkIfExists); - $this->consoleOutput->expects($this->any()) - ->method('writeln') + $this->consoleOutput->method('writeln') ->with($this->stringContains($expectedMessage)); - $this->assertSame($expectedReturn, $this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput])); + $this->assertSame($expectedReturn, self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput])); } } diff --git a/tests/Core/Command/Config/App/GetConfigTest.php b/tests/Core/Command/Config/App/GetConfigTest.php index 521ecfbfb40..13392cddf55 100644 --- a/tests/Core/Command/Config/App/GetConfigTest.php +++ b/tests/Core/Command/Config/App/GetConfigTest.php @@ -1,59 +1,44 @@ <?php + +declare(strict_types=1); /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Config\App; +use OC\Config\ConfigManager; use OC\Core\Command\Config\App\GetConfig; -use OCP\IConfig; +use OCP\Exceptions\AppConfigUnknownKeyException; +use OCP\IAppConfig; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; class GetConfigTest extends TestCase { - /** @var \PHPUnit\Framework\MockObject\MockObject */ - protected $config; - - /** @var \PHPUnit\Framework\MockObject\MockObject */ - protected $consoleInput; - /** @var \PHPUnit\Framework\MockObject\MockObject */ - protected $consoleOutput; - - /** @var \Symfony\Component\Console\Command\Command */ - protected $command; + protected IAppConfig&MockObject $appConfig; + protected ConfigManager&MockObject $configManager; + protected InputInterface&MockObject $consoleInput; + protected OutputInterface&MockObject $consoleOutput; + protected Command $command; protected function setUp(): void { parent::setUp(); - $config = $this->config = $this->getMockBuilder(IConfig::class) - ->disableOriginalConstructor() - ->getMock(); - $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); - $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); + $this->appConfig = $this->createMock(IAppConfig::class); + $this->configManager = $this->createMock(ConfigManager::class); + $this->consoleInput = $this->createMock(InputInterface::class); + $this->consoleOutput = $this->createMock(OutputInterface::class); - /** @var \OCP\IConfig $config */ - $this->command = new GetConfig($config); + $this->command = new GetConfig($this->appConfig, $this->configManager); } - public function getData() { + public static function dataGet(): array { return [ // String output as json ['name', 'newvalue', true, null, false, 'json', 0, json_encode('newvalue')], @@ -95,47 +80,36 @@ class GetConfigTest extends TestCase { ]; } - /** - * @dataProvider getData - * - * @param string $configName - * @param mixed $value - * @param bool $configExists - * @param mixed $defaultValue - * @param bool $hasDefault - * @param string $outputFormat - * @param int $expectedReturn - * @param string $expectedMessage - */ - public function testGet($configName, $value, $configExists, $defaultValue, $hasDefault, $outputFormat, $expectedReturn, $expectedMessage) { - $this->config->expects($this->atLeastOnce()) - ->method('getAppKeys') - ->with('app-name') - ->willReturn($configExists ? [$configName] : []); - + #[\PHPUnit\Framework\Attributes\DataProvider('dataGet')] + public function testGet(string $configName, mixed $value, bool $configExists, mixed $defaultValue, bool $hasDefault, string $outputFormat, int $expectedReturn, ?string $expectedMessage): void { if (!$expectedReturn) { if ($configExists) { - $this->config->expects($this->once()) - ->method('getAppValue') + $this->appConfig->expects($this->once()) + ->method('getDetails') ->with('app-name', $configName) - ->willReturn($value); + ->willReturn(['value' => $value]); } } + if (!$configExists) { + $this->appConfig->expects($this->once()) + ->method('getDetails') + ->with('app-name', $configName) + ->willThrowException(new AppConfigUnknownKeyException()); + } + $this->consoleInput->expects($this->exactly(2)) ->method('getArgument') ->willReturnMap([ ['app', 'app-name'], ['name', $configName], ]); - $this->consoleInput->expects($this->any()) - ->method('getOption') + $this->consoleInput->method('getOption') ->willReturnMap([ ['default-value', $defaultValue], ['output', $outputFormat], ]); - $this->consoleInput->expects($this->any()) - ->method('hasParameterOption') + $this->consoleInput->method('hasParameterOption') ->willReturnMap([ ['--output', false, true], ['--default-value', false, $hasDefault], @@ -145,8 +119,7 @@ class GetConfigTest extends TestCase { global $output; $output = ''; - $this->consoleOutput->expects($this->any()) - ->method('writeln') + $this->consoleOutput->method('writeln') ->willReturnCallback(function ($value) { global $output; $output .= $value . "\n"; @@ -154,7 +127,7 @@ class GetConfigTest extends TestCase { }); } - $this->assertSame($expectedReturn, $this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput])); + $this->assertSame($expectedReturn, self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput])); if ($expectedMessage !== null) { global $output; diff --git a/tests/Core/Command/Config/App/SetConfigTest.php b/tests/Core/Command/Config/App/SetConfigTest.php index 88053f8c189..a5c62368163 100644 --- a/tests/Core/Command/Config/App/SetConfigTest.php +++ b/tests/Core/Command/Config/App/SetConfigTest.php @@ -1,59 +1,45 @@ <?php + +declare(strict_types=1); /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Config\App; +use OC\AppConfig; +use OC\Config\ConfigManager; use OC\Core\Command\Config\App\SetConfig; -use OCP\IConfig; +use OCP\Exceptions\AppConfigUnknownKeyException; +use OCP\IAppConfig; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; class SetConfigTest extends TestCase { - /** @var \PHPUnit\Framework\MockObject\MockObject */ - protected $config; - - /** @var \PHPUnit\Framework\MockObject\MockObject */ - protected $consoleInput; - /** @var \PHPUnit\Framework\MockObject\MockObject */ - protected $consoleOutput; - - /** @var \Symfony\Component\Console\Command\Command */ - protected $command; + protected IAppConfig&MockObject $appConfig; + protected ConfigManager&MockObject $configManager; + protected InputInterface&MockObject $consoleInput; + protected OutputInterface&MockObject $consoleOutput; + protected Command $command; protected function setUp(): void { parent::setUp(); - $config = $this->config = $this->getMockBuilder(IConfig::class) - ->disableOriginalConstructor() - ->getMock(); - $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); - $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); + $this->appConfig = $this->createMock(AppConfig::class); + $this->configManager = $this->createMock(ConfigManager::class); + $this->consoleInput = $this->createMock(InputInterface::class); + $this->consoleOutput = $this->createMock(OutputInterface::class); - /** @var \OCP\IConfig $config */ - $this->command = new SetConfig($config); + $this->command = new SetConfig($this->appConfig, $this->configManager); } - public function setData() { + public static function dataSet(): array { return [ [ 'name', @@ -74,25 +60,23 @@ class SetConfigTest extends TestCase { ]; } - /** - * @dataProvider setData - * - * @param string $configName - * @param mixed $newValue - * @param bool $configExists - * @param bool $updateOnly - * @param bool $updated - * @param string $expectedMessage - */ - public function testSet($configName, $newValue, $configExists, $updateOnly, $updated, $expectedMessage) { - $this->config->expects($this->once()) - ->method('getAppKeys') - ->with('app-name') - ->willReturn($configExists ? [$configName] : []); + #[\PHPUnit\Framework\Attributes\DataProvider('dataSet')] + public function testSet(string $configName, mixed $newValue, bool $configExists, bool $updateOnly, bool $updated, string $expectedMessage): void { + $this->appConfig->method('hasKey') + ->with('app-name', $configName) + ->willReturn($configExists); + + if (!$configExists) { + $this->appConfig->method('getValueType') + ->willThrowException(new AppConfigUnknownKeyException()); + } else { + $this->appConfig->method('getValueType') + ->willReturn(IAppConfig::VALUE_MIXED); + } if ($updated) { - $this->config->expects($this->once()) - ->method('setAppValue') + $this->appConfig->expects($this->once()) + ->method('setValueMixed') ->with('app-name', $configName, $newValue); } @@ -102,19 +86,22 @@ class SetConfigTest extends TestCase { ['app', 'app-name'], ['name', $configName], ]); - $this->consoleInput->expects($this->any()) - ->method('getOption') - ->with('value') - ->willReturn($newValue); - $this->consoleInput->expects($this->any()) - ->method('hasParameterOption') - ->with('--update-only') - ->willReturn($updateOnly); - - $this->consoleOutput->expects($this->any()) - ->method('writeln') + $this->consoleInput->method('getOption') + ->willReturnMap([ + ['value', $newValue], + ['lazy', null], + ['sensitive', null], + ['no-interaction', true], + ]); + $this->consoleInput->method('hasParameterOption') + ->willReturnMap([ + ['--type', false, false], + ['--value', false, true], + ['--update-only', false, $updateOnly] + ]); + $this->consoleOutput->method('writeln') ->with($this->stringContains($expectedMessage)); - $this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); + self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } } diff --git a/tests/Core/Command/Config/ImportTest.php b/tests/Core/Command/Config/ImportTest.php index c9cc256bea9..14cdd714d12 100644 --- a/tests/Core/Command/Config/ImportTest.php +++ b/tests/Core/Command/Config/ImportTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Config; @@ -48,11 +35,11 @@ class ImportTest extends TestCase { $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); - /** @var \OCP\IConfig $config */ + /** @var IConfig $config */ $this->command = new Import($config); } - public function validateAppsArrayData() { + public static function validateAppsArrayData(): array { return [ [0], [1], @@ -63,16 +50,15 @@ class ImportTest extends TestCase { } /** - * @dataProvider validateAppsArrayData - * * @param mixed $configValue */ - public function testValidateAppsArray($configValue) { + #[\PHPUnit\Framework\Attributes\DataProvider('validateAppsArrayData')] + public function testValidateAppsArray($configValue): void { $this->invokePrivate($this->command, 'validateAppsArray', [['app' => ['name' => $configValue]]]); $this->assertTrue(true, 'Asserting that no exception is thrown'); } - public function validateAppsArrayThrowsData() { + public static function validateAppsArrayThrowsData(): array { return [ [false], [true], @@ -82,11 +68,10 @@ class ImportTest extends TestCase { } /** - * @dataProvider validateAppsArrayThrowsData - * * @param mixed $configValue */ - public function testValidateAppsArrayThrows($configValue) { + #[\PHPUnit\Framework\Attributes\DataProvider('validateAppsArrayThrowsData')] + public function testValidateAppsArrayThrows($configValue): void { try { $this->invokePrivate($this->command, 'validateAppsArray', [['app' => ['name' => $configValue]]]); $this->fail('Did not throw expected UnexpectedValueException'); @@ -95,7 +80,7 @@ class ImportTest extends TestCase { } } - public function checkTypeRecursivelyData() { + public static function checkTypeRecursivelyData(): array { return [ [0], [1], @@ -112,16 +97,15 @@ class ImportTest extends TestCase { } /** - * @dataProvider checkTypeRecursivelyData - * * @param mixed $configValue */ - public function testCheckTypeRecursively($configValue) { + #[\PHPUnit\Framework\Attributes\DataProvider('checkTypeRecursivelyData')] + public function testCheckTypeRecursively($configValue): void { $this->invokePrivate($this->command, 'checkTypeRecursively', [$configValue, 'name']); $this->assertTrue(true, 'Asserting that no exception is thrown'); } - public function checkTypeRecursivelyThrowsData() { + public static function checkTypeRecursivelyThrowsData(): array { return [ [new \Exception()], [[new \Exception()]], @@ -131,11 +115,10 @@ class ImportTest extends TestCase { } /** - * @dataProvider checkTypeRecursivelyThrowsData - * * @param mixed $configValue */ - public function testCheckTypeRecursivelyThrows($configValue) { + #[\PHPUnit\Framework\Attributes\DataProvider('checkTypeRecursivelyThrowsData')] + public function testCheckTypeRecursivelyThrows($configValue): void { try { $this->invokePrivate($this->command, 'checkTypeRecursively', [$configValue, 'name']); $this->fail('Did not throw expected UnexpectedValueException'); @@ -144,7 +127,7 @@ class ImportTest extends TestCase { } } - public function validateArrayData() { + public static function validateArrayData(): array { return [ [['system' => []]], [['apps' => []]], @@ -153,16 +136,15 @@ class ImportTest extends TestCase { } /** - * @dataProvider validateArrayData - * * @param array $configArray */ - public function testValidateArray($configArray) { + #[\PHPUnit\Framework\Attributes\DataProvider('validateArrayData')] + public function testValidateArray($configArray): void { $this->invokePrivate($this->command, 'validateArray', [$configArray]); $this->assertTrue(true, 'Asserting that no exception is thrown'); } - public function validateArrayThrowsData() { + public static function validateArrayThrowsData(): array { return [ [[], 'At least one key of the following is expected:'], [[0 => []], 'Found invalid entries in root'], @@ -171,12 +153,12 @@ class ImportTest extends TestCase { } /** - * @dataProvider validateArrayThrowsData * * @param mixed $configArray * @param string $expectedException */ - public function testValidateArrayThrows($configArray, $expectedException) { + #[\PHPUnit\Framework\Attributes\DataProvider('validateArrayThrowsData')] + public function testValidateArrayThrows($configArray, $expectedException): void { try { $this->invokePrivate($this->command, 'validateArray', [$configArray]); $this->fail('Did not throw expected UnexpectedValueException'); diff --git a/tests/Core/Command/Config/ListConfigsTest.php b/tests/Core/Command/Config/ListConfigsTest.php index 01d5f512494..e4af55116c0 100644 --- a/tests/Core/Command/Config/ListConfigsTest.php +++ b/tests/Core/Command/Config/ListConfigsTest.php @@ -1,26 +1,14 @@ <?php + /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Config; +use OC\Config\ConfigManager; use OC\Core\Command\Config\ListConfigs; use OC\SystemConfig; use OCP\IAppConfig; @@ -34,6 +22,8 @@ class ListConfigsTest extends TestCase { protected $appConfig; /** @var \PHPUnit\Framework\MockObject\MockObject */ protected $systemConfig; + /** @var \PHPUnit\Framework\MockObject\MockObject */ + protected $configManager; /** @var \PHPUnit\Framework\MockObject\MockObject */ protected $consoleInput; @@ -52,15 +42,20 @@ class ListConfigsTest extends TestCase { $appConfig = $this->appConfig = $this->getMockBuilder(IAppConfig::class) ->disableOriginalConstructor() ->getMock(); + $configManager = $this->configManager = $this->getMockBuilder(ConfigManager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); /** @var \OC\SystemConfig $systemConfig */ /** @var \OCP\IAppConfig $appConfig */ - $this->command = new ListConfigs($systemConfig, $appConfig); + /** @var ConfigManager $configManager */ + $this->command = new ListConfigs($systemConfig, $appConfig, $configManager); } - public function listData() { + public static function listData(): array { return [ [ 'all', @@ -75,10 +70,10 @@ class ListConfigsTest extends TestCase { ], // app config [ - ['files', false, [ + ['files', [ 'enabled' => 'yes', ]], - ['core', false, [ + ['core', [ 'global_cache_gc_lastrun' => '1430388388', ]], ], @@ -155,10 +150,10 @@ class ListConfigsTest extends TestCase { ], // app config [ - ['files', false, [ + ['files', [ 'enabled' => 'yes', ]], - ['core', false, [ + ['core', [ 'global_cache_gc_lastrun' => '1430388388', ]], ], @@ -190,10 +185,10 @@ class ListConfigsTest extends TestCase { ], // app config [ - ['files', false, [ + ['files', [ 'enabled' => 'yes', ]], - ['core', false, [ + ['core', [ 'global_cache_gc_lastrun' => '1430388388', ]], ], @@ -218,10 +213,10 @@ class ListConfigsTest extends TestCase { ], // app config [ - ['files', false, [ + ['files', [ 'enabled' => 'yes', ]], - ['core', false, [ + ['core', [ 'global_cache_gc_lastrun' => '1430388388', ]], ], @@ -267,7 +262,6 @@ class ListConfigsTest extends TestCase { } /** - * @dataProvider listData * * @param string $app * @param array $systemConfigs @@ -276,7 +270,8 @@ class ListConfigsTest extends TestCase { * @param bool $private * @param string $expected */ - public function testList($app, $systemConfigs, $systemConfigMap, $appConfig, $private, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('listData')] + public function testList($app, $systemConfigs, $systemConfigMap, $appConfig, $private, $expected): void { $this->systemConfig->expects($this->any()) ->method('getKeys') ->willReturn($systemConfigs); diff --git a/tests/Core/Command/Config/System/CastHelperTest.php b/tests/Core/Command/Config/System/CastHelperTest.php new file mode 100644 index 00000000000..924887daaf7 --- /dev/null +++ b/tests/Core/Command/Config/System/CastHelperTest.php @@ -0,0 +1,66 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +namespace Core\Command\Config\System; + +use OC\Core\Command\Config\System\CastHelper; +use Test\TestCase; + +class CastHelperTest extends TestCase { + private CastHelper $castHelper; + + protected function setUp(): void { + parent::setUp(); + $this->castHelper = new CastHelper(); + } + + public static function castValueProvider(): array { + return [ + [null, 'string', ['value' => '', 'readable-value' => 'empty string']], + + ['abc', 'string', ['value' => 'abc', 'readable-value' => 'string abc']], + + ['123', 'integer', ['value' => 123, 'readable-value' => 'integer 123']], + ['456', 'int', ['value' => 456, 'readable-value' => 'integer 456']], + + ['2.25', 'double', ['value' => 2.25, 'readable-value' => 'double 2.25']], + ['0.5', 'float', ['value' => 0.5, 'readable-value' => 'double 0.5']], + + ['', 'null', ['value' => null, 'readable-value' => 'null']], + + ['true', 'boolean', ['value' => true, 'readable-value' => 'boolean true']], + ['false', 'bool', ['value' => false, 'readable-value' => 'boolean false']], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('castValueProvider')] + public function testCastValue($value, $type, $expectedValue): void { + $this->assertSame( + $expectedValue, + $this->castHelper->castValue($value, $type) + ); + } + + public static function castValueInvalidProvider(): array { + return [ + ['123', 'foobar'], + + [null, 'integer'], + ['abc', 'integer'], + ['76ggg', 'double'], + ['true', 'float'], + ['foobar', 'boolean'], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('castValueInvalidProvider')] + public function testCastValueInvalid($value, $type): void { + $this->expectException(\InvalidArgumentException::class); + + $this->castHelper->castValue($value, $type); + } +} diff --git a/tests/Core/Command/Config/System/DeleteConfigTest.php b/tests/Core/Command/Config/System/DeleteConfigTest.php index b72f06b35bf..b0a3580e1cd 100644 --- a/tests/Core/Command/Config/System/DeleteConfigTest.php +++ b/tests/Core/Command/Config/System/DeleteConfigTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Config\System; @@ -48,11 +35,11 @@ class DeleteConfigTest extends TestCase { $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); - /** @var \OC\SystemConfig $systemConfig */ + /** @var SystemConfig $systemConfig */ $this->command = new DeleteConfig($systemConfig); } - public function deleteData() { + public static function deleteData(): array { return [ [ 'name1', @@ -86,7 +73,6 @@ class DeleteConfigTest extends TestCase { } /** - * @dataProvider deleteData * * @param string $configName * @param bool $configExists @@ -94,7 +80,8 @@ class DeleteConfigTest extends TestCase { * @param int $expectedReturn * @param string $expectedMessage */ - public function testDelete($configName, $configExists, $checkIfExists, $expectedReturn, $expectedMessage) { + #[\PHPUnit\Framework\Attributes\DataProvider('deleteData')] + public function testDelete($configName, $configExists, $checkIfExists, $expectedReturn, $expectedMessage): void { $this->systemConfig->expects(($checkIfExists) ? $this->once() : $this->never()) ->method('getKeys') ->willReturn($configExists ? [$configName] : []); @@ -119,7 +106,7 @@ class DeleteConfigTest extends TestCase { $this->assertSame($expectedReturn, $this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput])); } - public function deleteArrayData() { + public static function deleteArrayData(): array { return [ [ ['name', 'sub'], @@ -179,7 +166,6 @@ class DeleteConfigTest extends TestCase { } /** - * @dataProvider deleteArrayData * * @param string[] $configNames * @param bool $configKeyExists @@ -189,7 +175,8 @@ class DeleteConfigTest extends TestCase { * @param int $expectedReturn * @param string $expectedMessage */ - public function testArrayDelete(array $configNames, $configKeyExists, $checkIfKeyExists, $configValue, $updateValue, $expectedReturn, $expectedMessage) { + #[\PHPUnit\Framework\Attributes\DataProvider('deleteArrayData')] + public function testArrayDelete(array $configNames, $configKeyExists, $checkIfKeyExists, $configValue, $updateValue, $expectedReturn, $expectedMessage): void { $this->systemConfig->expects(($checkIfKeyExists) ? $this->once() : $this->never()) ->method('getKeys') ->willReturn($configKeyExists ? [$configNames[0]] : []); diff --git a/tests/Core/Command/Config/System/GetConfigTest.php b/tests/Core/Command/Config/System/GetConfigTest.php index 3a6bb1acb50..8b84fd14198 100644 --- a/tests/Core/Command/Config/System/GetConfigTest.php +++ b/tests/Core/Command/Config/System/GetConfigTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Config\System; @@ -48,12 +35,12 @@ class GetConfigTest extends TestCase { $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); - /** @var \OC\SystemConfig $systemConfig */ + /** @var SystemConfig $systemConfig */ $this->command = new GetConfig($systemConfig); } - public function getData() { + public static function getData(): array { return [ // String output as json ['name', 'newvalue', true, null, false, 'json', 0, json_encode('newvalue')], @@ -102,7 +89,6 @@ class GetConfigTest extends TestCase { } /** - * @dataProvider getData * * @param string[] $configNames * @param mixed $value @@ -113,7 +99,8 @@ class GetConfigTest extends TestCase { * @param int $expectedReturn * @param string $expectedMessage */ - public function testGet($configNames, $value, $configExists, $defaultValue, $hasDefault, $outputFormat, $expectedReturn, $expectedMessage) { + #[\PHPUnit\Framework\Attributes\DataProvider('getData')] + public function testGet($configNames, $value, $configExists, $defaultValue, $hasDefault, $outputFormat, $expectedReturn, $expectedMessage): void { if (is_array($configNames)) { $configName = $configNames[0]; } else { diff --git a/tests/Core/Command/Config/System/SetConfigTest.php b/tests/Core/Command/Config/System/SetConfigTest.php index a53607e8a39..a99b832c160 100644 --- a/tests/Core/Command/Config/System/SetConfigTest.php +++ b/tests/Core/Command/Config/System/SetConfigTest.php @@ -1,26 +1,14 @@ <?php + /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Config\System; +use OC\Core\Command\Config\System\CastHelper; use OC\Core\Command\Config\System\SetConfig; use OC\SystemConfig; use Symfony\Component\Console\Input\InputInterface; @@ -48,12 +36,12 @@ class SetConfigTest extends TestCase { $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); - /** @var \OC\SystemConfig $systemConfig */ - $this->command = new SetConfig($systemConfig); + /** @var SystemConfig $systemConfig */ + $this->command = new SetConfig($systemConfig, new CastHelper()); } - public function setData() { + public static function dataTest() { return [ [['name'], 'newvalue', null, 'newvalue'], [['a', 'b', 'c'], 'foobar', null, ['b' => ['c' => 'foobar']]], @@ -62,14 +50,14 @@ class SetConfigTest extends TestCase { } /** - * @dataProvider setData * * @param array $configNames * @param string $newValue * @param mixed $existingData * @param mixed $expectedValue */ - public function testSet($configNames, $newValue, $existingData, $expectedValue) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTest')] + public function testSet($configNames, $newValue, $existingData, $expectedValue): void { $this->systemConfig->expects($this->once()) ->method('setValue') ->with($configNames[0], $expectedValue); @@ -90,7 +78,7 @@ class SetConfigTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function setUpdateOnlyProvider() { + public static function setUpdateOnlyProvider(): array { return [ [['name'], null], [['a', 'b', 'c'], null], @@ -99,10 +87,8 @@ class SetConfigTest extends TestCase { ]; } - /** - * @dataProvider setUpdateOnlyProvider - */ - public function testSetUpdateOnly($configNames, $existingData) { + #[\PHPUnit\Framework\Attributes\DataProvider('setUpdateOnlyProvider')] + public function testSetUpdateOnly($configNames, $existingData): void { $this->expectException(\UnexpectedValueException::class); $this->systemConfig->expects($this->never()) @@ -126,53 +112,4 @@ class SetConfigTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - - public function castValueProvider() { - return [ - [null, 'string', ['value' => '', 'readable-value' => 'empty string']], - - ['abc', 'string', ['value' => 'abc', 'readable-value' => 'string abc']], - - ['123', 'integer', ['value' => 123, 'readable-value' => 'integer 123']], - ['456', 'int', ['value' => 456, 'readable-value' => 'integer 456']], - - ['2.25', 'double', ['value' => 2.25, 'readable-value' => 'double 2.25']], - ['0.5', 'float', ['value' => 0.5, 'readable-value' => 'double 0.5']], - - ['', 'null', ['value' => null, 'readable-value' => 'null']], - - ['true', 'boolean', ['value' => true, 'readable-value' => 'boolean true']], - ['false', 'bool', ['value' => false, 'readable-value' => 'boolean false']], - ]; - } - - /** - * @dataProvider castValueProvider - */ - public function testCastValue($value, $type, $expectedValue) { - $this->assertSame($expectedValue, - $this->invokePrivate($this->command, 'castValue', [$value, $type]) - ); - } - - public function castValueInvalidProvider() { - return [ - ['123', 'foobar'], - - [null, 'integer'], - ['abc', 'integer'], - ['76ggg', 'double'], - ['true', 'float'], - ['foobar', 'boolean'], - ]; - } - - /** - * @dataProvider castValueInvalidProvider - */ - public function testCastValueInvalid($value, $type) { - $this->expectException(\InvalidArgumentException::class); - - $this->invokePrivate($this->command, 'castValue', [$value, $type]); - } } diff --git a/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php b/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php index 1d5e2ac420d..0bc6cbb64cf 100644 --- a/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php +++ b/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php @@ -1,27 +1,15 @@ <?php + /** - * @author Björn Schießle <schiessle@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Encryption; use OC\Core\Command\Encryption\ChangeKeyStorageRoot; +use OC\Encryption\Keys\Storage; use OC\Encryption\Util; use OC\Files\View; use OCP\IConfig; @@ -46,7 +34,7 @@ class ChangeKeyStorageRootTest extends TestCase { /** @var IConfig | \PHPUnit\Framework\MockObject\MockObject */ protected $config; - /** @var Util | \PHPUnit\Framework\MockObject\MockObject */ + /** @var Util | \PHPUnit\Framework\MockObject\MockObject */ protected $util; /** @var QuestionHelper | \PHPUnit\Framework\MockObject\MockObject */ @@ -58,7 +46,7 @@ class ChangeKeyStorageRootTest extends TestCase { /** @var OutputInterface | \PHPUnit\Framework\MockObject\MockObject */ protected $outputInterface; - /** @var \OCP\UserInterface | \PHPUnit\Framework\MockObject\MockObject */ + /** @var UserInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $userInterface; protected function setUp(): void { @@ -75,6 +63,7 @@ class ChangeKeyStorageRootTest extends TestCase { /* We need format method to return a string */ $outputFormatter = $this->createMock(OutputFormatterInterface::class); + $outputFormatter->method('isDecorated')->willReturn(false); $outputFormatter->method('format')->willReturnArgument(0); $this->outputInterface->expects($this->any())->method('getFormatter') @@ -89,10 +78,8 @@ class ChangeKeyStorageRootTest extends TestCase { ); } - /** - * @dataProvider dataTestExecute - */ - public function testExecute($newRoot, $answer, $successMoveKey) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestExecute')] + public function testExecute($newRoot, $answer, $successMoveKey): void { $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot') ->setConstructorArgs( [ @@ -102,7 +89,7 @@ class ChangeKeyStorageRootTest extends TestCase { $this->util, $this->questionHelper ] - )->setMethods(['moveAllKeys'])->getMock(); + )->onlyMethods(['moveAllKeys'])->getMock(); $this->util->expects($this->once())->method('getKeyStorageRoot') ->willReturn(''); @@ -135,7 +122,7 @@ class ChangeKeyStorageRootTest extends TestCase { ); } - public function dataTestExecute() { + public static function dataTestExecute(): array { return [ [null, true, true], [null, true, false], @@ -145,8 +132,8 @@ class ChangeKeyStorageRootTest extends TestCase { ]; } - public function testMoveAllKeys() { - /** @var \OC\Core\Command\Encryption\ChangeKeyStorageRoot $changeKeyStorageRoot */ + public function testMoveAllKeys(): void { + /** @var ChangeKeyStorageRoot $changeKeyStorageRoot */ $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot') ->setConstructorArgs( [ @@ -156,33 +143,33 @@ class ChangeKeyStorageRootTest extends TestCase { $this->util, $this->questionHelper ] - )->setMethods(['prepareNewRoot', 'moveSystemKeys', 'moveUserKeys'])->getMock(); + )->onlyMethods(['prepareNewRoot', 'moveSystemKeys', 'moveUserKeys'])->getMock(); - $changeKeyStorageRoot->expects($this->at(0))->method('prepareNewRoot')->with('newRoot'); - $changeKeyStorageRoot->expects($this->at(1))->method('moveSystemKeys')->with('oldRoot', 'newRoot'); - $changeKeyStorageRoot->expects($this->at(2))->method('moveUserKeys')->with('oldRoot', 'newRoot', $this->outputInterface); + $changeKeyStorageRoot->expects($this->once())->method('prepareNewRoot')->with('newRoot'); + $changeKeyStorageRoot->expects($this->once())->method('moveSystemKeys')->with('oldRoot', 'newRoot'); + $changeKeyStorageRoot->expects($this->once())->method('moveUserKeys')->with('oldRoot', 'newRoot', $this->outputInterface); $this->invokePrivate($changeKeyStorageRoot, 'moveAllKeys', ['oldRoot', 'newRoot', $this->outputInterface]); } - public function testPrepareNewRoot() { + public function testPrepareNewRoot(): void { $this->view->expects($this->once())->method('is_dir')->with('newRoot') ->willReturn(true); $this->view->expects($this->once())->method('file_put_contents') - ->with('newRoot/' . \OC\Encryption\Keys\Storage::KEY_STORAGE_MARKER, + ->with('newRoot/' . Storage::KEY_STORAGE_MARKER, 'Nextcloud will detect this folder as key storage root only if this file exists')->willReturn(true); $this->invokePrivate($this->changeKeyStorageRoot, 'prepareNewRoot', ['newRoot']); } /** - * @dataProvider dataTestPrepareNewRootException * * @param bool $dirExists * @param bool $couldCreateFile */ - public function testPrepareNewRootException($dirExists, $couldCreateFile) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestPrepareNewRootException')] + public function testPrepareNewRootException($dirExists, $couldCreateFile): void { $this->expectException(\Exception::class); $this->view->expects($this->once())->method('is_dir')->with('newRoot') @@ -192,7 +179,7 @@ class ChangeKeyStorageRootTest extends TestCase { $this->invokePrivate($this->changeKeyStorageRoot, 'prepareNewRoot', ['newRoot']); } - public function dataTestPrepareNewRootException() { + public static function dataTestPrepareNewRootException(): array { return [ [true, false], [true, null], @@ -201,13 +188,13 @@ class ChangeKeyStorageRootTest extends TestCase { } /** - * @dataProvider dataTestMoveSystemKeys * * @param bool $dirExists * @param bool $targetExists * @param bool $executeRename */ - public function testMoveSystemKeys($dirExists, $targetExists, $executeRename) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestMoveSystemKeys')] + public function testMoveSystemKeys($dirExists, $targetExists, $executeRename): void { $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot') ->setConstructorArgs( [ @@ -217,7 +204,7 @@ class ChangeKeyStorageRootTest extends TestCase { $this->util, $this->questionHelper ] - )->setMethods(['targetExists'])->getMock(); + )->onlyMethods(['targetExists'])->getMock(); $this->view->expects($this->once())->method('is_dir') ->with('oldRoot/files_encryption')->willReturn($dirExists); @@ -226,7 +213,7 @@ class ChangeKeyStorageRootTest extends TestCase { if ($executeRename) { $this->view->expects($this->once())->method('rename') - ->with('oldRoot/files_encryption', 'newRoot/files_encryption'); + ->with('oldRoot/files_encryption', 'newRoot/files_encryption'); } else { $this->view->expects($this->never())->method('rename'); } @@ -234,7 +221,7 @@ class ChangeKeyStorageRootTest extends TestCase { $this->invokePrivate($changeKeyStorageRoot, 'moveSystemKeys', ['oldRoot', 'newRoot']); } - public function dataTestMoveSystemKeys() { + public static function dataTestMoveSystemKeys(): array { return [ [true, false, true], [false, true, false], @@ -244,7 +231,7 @@ class ChangeKeyStorageRootTest extends TestCase { } - public function testMoveUserKeys() { + public function testMoveUserKeys(): void { $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot') ->setConstructorArgs( [ @@ -254,7 +241,7 @@ class ChangeKeyStorageRootTest extends TestCase { $this->util, $this->questionHelper ] - )->setMethods(['setupUserFS', 'moveUserEncryptionFolder'])->getMock(); + )->onlyMethods(['setupUserFS', 'moveUserEncryptionFolder'])->getMock(); $this->userManager->expects($this->once())->method('getBackends') ->willReturn([$this->userInterface]); @@ -267,14 +254,14 @@ class ChangeKeyStorageRootTest extends TestCase { } /** - * @dataProvider dataTestMoveUserEncryptionFolder * * @param bool $userExists * @param bool $isDir * @param bool $targetExists * @param bool $shouldRename */ - public function testMoveUserEncryptionFolder($userExists, $isDir, $targetExists, $shouldRename) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestMoveUserEncryptionFolder')] + public function testMoveUserEncryptionFolder($userExists, $isDir, $targetExists, $shouldRename): void { $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot') ->setConstructorArgs( [ @@ -284,7 +271,7 @@ class ChangeKeyStorageRootTest extends TestCase { $this->util, $this->questionHelper ] - )->setMethods(['targetExists', 'prepareParentFolder'])->getMock(); + )->onlyMethods(['targetExists', 'prepareParentFolder'])->getMock(); $this->userManager->expects($this->once())->method('userExists') ->willReturn($userExists); @@ -306,7 +293,7 @@ class ChangeKeyStorageRootTest extends TestCase { $this->invokePrivate($changeKeyStorageRoot, 'moveUserEncryptionFolder', ['user1', 'oldRoot', 'newRoot']); } - public function dataTestMoveUserEncryptionFolder() { + public static function dataTestMoveUserEncryptionFolder(): array { return [ [true, true, false, true], [true, false, true, false], @@ -319,10 +306,8 @@ class ChangeKeyStorageRootTest extends TestCase { } - /** - * @dataProvider dataTestPrepareParentFolder - */ - public function testPrepareParentFolder($path, $pathExists) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestPrepareParentFolder')] + public function testPrepareParentFolder($path, $pathExists): void { $this->view->expects($this->any())->method('file_exists') ->willReturnCallback( function ($fileExistsPath) use ($path, $pathExists) { @@ -347,14 +332,14 @@ class ChangeKeyStorageRootTest extends TestCase { ); } - public function dataTestPrepareParentFolder() { + public static function dataTestPrepareParentFolder(): array { return [ ['/user/folder/sub_folder/keystorage', true], ['/user/folder/sub_folder/keystorage', false] ]; } - public function testTargetExists() { + public function testTargetExists(): void { $this->view->expects($this->once())->method('file_exists')->with('path') ->willReturn(false); @@ -364,7 +349,7 @@ class ChangeKeyStorageRootTest extends TestCase { } - public function testTargetExistsException() { + public function testTargetExistsException(): void { $this->expectException(\Exception::class); $this->view->expects($this->once())->method('file_exists')->with('path') diff --git a/tests/Core/Command/Encryption/DecryptAllTest.php b/tests/Core/Command/Encryption/DecryptAllTest.php index c78500fd9d8..41d9e4c713f 100644 --- a/tests/Core/Command/Encryption/DecryptAllTest.php +++ b/tests/Core/Command/Encryption/DecryptAllTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Björn Schießle <schiessle@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Encryption; @@ -31,16 +18,16 @@ use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; class DecryptAllTest extends TestCase { - /** @var \PHPUnit\Framework\MockObject\MockObject | \OCP\IConfig */ + /** @var \PHPUnit\Framework\MockObject\MockObject|IConfig */ protected $config; - /** @var \PHPUnit\Framework\MockObject\MockObject | \OCP\Encryption\IManager */ + /** @var \PHPUnit\Framework\MockObject\MockObject | \OCP\Encryption\IManager */ protected $encryptionManager; - /** @var \PHPUnit\Framework\MockObject\MockObject | \OCP\App\IAppManager */ + /** @var \PHPUnit\Framework\MockObject\MockObject|IAppManager */ protected $appManager; - /** @var \PHPUnit\Framework\MockObject\MockObject | \Symfony\Component\Console\Input\InputInterface */ + /** @var \PHPUnit\Framework\MockObject\MockObject | \Symfony\Component\Console\Input\InputInterface */ protected $consoleInput; /** @var \PHPUnit\Framework\MockObject\MockObject | \Symfony\Component\Console\Output\OutputInterface */ @@ -84,19 +71,22 @@ class DecryptAllTest extends TestCase { ->with('files_trashbin')->willReturn(true); } - public function testMaintenanceAndTrashbin() { + public function testMaintenanceAndTrashbin(): void { // on construct we enable single-user-mode and disable the trash bin - $this->config->expects($this->at(1)) + // on destruct we disable single-user-mode again and enable the trash bin + $calls = [ + ['maintenance', true], + ['maintenance', false], + ]; + $this->config->expects($this->exactly(2)) ->method('setSystemValue') - ->with('maintenance', true); + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, func_get_args()); + }); $this->appManager->expects($this->once()) ->method('disableApp') ->with('files_trashbin'); - - // on destruct wi disable single-user-mode again and enable the trash bin - $this->config->expects($this->at(2)) - ->method('setSystemValue') - ->with('maintenance', false); $this->appManager->expects($this->once()) ->method('enableApp') ->with('files_trashbin'); @@ -120,10 +110,8 @@ class DecryptAllTest extends TestCase { $this->invokePrivate($instance, 'resetMaintenanceAndTrashbin'); } - /** - * @dataProvider dataTestExecute - */ - public function testExecute($encryptionEnabled, $continue) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestExecute')] + public function testExecute($encryptionEnabled, $continue): void { $instance = new DecryptAll( $this->encryptionManager, $this->appManager, @@ -142,9 +130,16 @@ class DecryptAllTest extends TestCase { ->willReturn('user1'); if ($encryptionEnabled) { - $this->config->expects($this->at(1)) + $calls = [ + ['core', 'encryption_enabled', 'no'], + ['core', 'encryption_enabled', 'yes'], + ]; + $this->config->expects($this->exactly(2)) ->method('setAppValue') - ->with('core', 'encryption_enabled', 'no'); + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, func_get_args()); + }); $this->questionHelper->expects($this->once()) ->method('ask') ->willReturn($continue); @@ -154,9 +149,6 @@ class DecryptAllTest extends TestCase { ->with($this->consoleInput, $this->consoleOutput, 'user1'); } else { $this->decryptAll->expects($this->never())->method('decryptAll'); - $this->config->expects($this->at(2)) - ->method('setAppValue') - ->with('core', 'encryption_enabled', 'yes'); } } else { $this->config->expects($this->never())->method('setAppValue'); @@ -167,7 +159,7 @@ class DecryptAllTest extends TestCase { $this->invokePrivate($instance, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function dataTestExecute() { + public static function dataTestExecute(): array { return [ [true, true], [true, false], @@ -177,7 +169,7 @@ class DecryptAllTest extends TestCase { } - public function testExecuteFailure() { + public function testExecuteFailure(): void { $this->expectException(\Exception::class); $instance = new DecryptAll( @@ -188,15 +180,17 @@ class DecryptAllTest extends TestCase { $this->questionHelper ); - $this->config->expects($this->at(1)) - ->method('setAppValue') - ->with('core', 'encryption_enabled', 'no'); - // make sure that we enable encryption again after a exception was thrown - $this->config->expects($this->at(4)) + $calls = [ + ['core', 'encryption_enabled', 'no'], + ['core', 'encryption_enabled', 'yes'], + ]; + $this->config->expects($this->exactly(2)) ->method('setAppValue') - ->with('core', 'encryption_enabled', 'yes'); - + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, func_get_args()); + }); $this->encryptionManager->expects($this->once()) ->method('isEnabled') ->willReturn(true); @@ -213,7 +207,7 @@ class DecryptAllTest extends TestCase { $this->decryptAll->expects($this->once()) ->method('decryptAll') ->with($this->consoleInput, $this->consoleOutput, 'user1') - ->willReturnCallback(function () { + ->willReturnCallback(function (): void { throw new \Exception(); }); diff --git a/tests/Core/Command/Encryption/DisableTest.php b/tests/Core/Command/Encryption/DisableTest.php index bd29caafec3..a89fd636e47 100644 --- a/tests/Core/Command/Encryption/DisableTest.php +++ b/tests/Core/Command/Encryption/DisableTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Encryption; @@ -47,12 +34,12 @@ class DisableTest extends TestCase { $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); - /** @var \OCP\IConfig $config */ + /** @var IConfig $config */ $this->command = new Disable($config); } - public function dataDisable() { + public static function dataDisable(): array { return [ ['yes', true, 'Encryption disabled'], ['no', false, 'Encryption is already disabled'], @@ -60,13 +47,13 @@ class DisableTest extends TestCase { } /** - * @dataProvider dataDisable * * @param string $oldStatus * @param bool $isUpdating * @param string $expectedString */ - public function testDisable($oldStatus, $isUpdating, $expectedString) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataDisable')] + public function testDisable($oldStatus, $isUpdating, $expectedString): void { $this->config->expects($this->once()) ->method('getAppValue') ->with('core', 'encryption_enabled', $this->anything()) diff --git a/tests/Core/Command/Encryption/EnableTest.php b/tests/Core/Command/Encryption/EnableTest.php index c1656054ecd..32d1a7576f5 100644 --- a/tests/Core/Command/Encryption/EnableTest.php +++ b/tests/Core/Command/Encryption/EnableTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Encryption; @@ -59,7 +46,7 @@ class EnableTest extends TestCase { } - public function dataEnable() { + public static function dataEnable(): array { return [ ['no', null, [], true, 'Encryption enabled', 'No encryption module is loaded'], ['yes', null, [], false, 'Encryption is already enabled', 'No encryption module is loaded'], @@ -69,53 +56,45 @@ class EnableTest extends TestCase { ]; } - /** - * @dataProvider dataEnable - * - * @param string $oldStatus - * @param string $defaultModule - * @param array $availableModules - * @param bool $isUpdating - * @param string $expectedString - * @param string $expectedDefaultModuleString - */ - public function testEnable($oldStatus, $defaultModule, $availableModules, $isUpdating, $expectedString, $expectedDefaultModuleString) { - $invokeCount = 0; - $this->config->expects($this->at($invokeCount)) - ->method('getAppValue') - ->with('core', 'encryption_enabled', $this->anything()) - ->willReturn($oldStatus); - $invokeCount++; - + #[\PHPUnit\Framework\Attributes\DataProvider('dataEnable')] + public function testEnable(string $oldStatus, ?string $defaultModule, array $availableModules, bool $isUpdating, string $expectedString, string $expectedDefaultModuleString): void { if ($isUpdating) { $this->config->expects($this->once()) ->method('setAppValue') ->with('core', 'encryption_enabled', 'yes'); - $invokeCount++; } $this->manager->expects($this->atLeastOnce()) ->method('getEncryptionModules') ->willReturn($availableModules); - if (!empty($availableModules)) { - $this->config->expects($this->at($invokeCount)) + if (empty($availableModules)) { + $this->config->expects($this->once()) ->method('getAppValue') - ->with('core', 'default_encryption_module', $this->anything()) - ->willReturn($defaultModule); + ->willReturnMap([ + ['core', 'encryption_enabled', 'no', $oldStatus], + ]); + } else { + $this->config->expects($this->exactly(2)) + ->method('getAppValue') + ->willReturnMap([ + ['core', 'encryption_enabled', 'no', $oldStatus], + ['core', 'default_encryption_module', null, $defaultModule], + ]); } - $this->consoleOutput->expects($this->at(0)) - ->method('writeln') - ->with($this->stringContains($expectedString)); - - $this->consoleOutput->expects($this->at(1)) - ->method('writeln') - ->with(''); - - $this->consoleOutput->expects($this->at(2)) + $calls = [ + [$expectedString, 0], + ['', 0], + [$expectedDefaultModuleString, 0], + ]; + $this->consoleOutput->expects($this->exactly(3)) ->method('writeln') - ->with($this->stringContains($expectedDefaultModuleString)); + ->willReturnCallback(function (string $message, int $level) use (&$calls): void { + $call = array_shift($calls); + $this->assertStringContainsString($call[0], $message); + $this->assertSame($call[1], $level); + }); self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } diff --git a/tests/Core/Command/Encryption/EncryptAllTest.php b/tests/Core/Command/Encryption/EncryptAllTest.php index 1190a98843f..15cbe83737d 100644 --- a/tests/Core/Command/Encryption/EncryptAllTest.php +++ b/tests/Core/Command/Encryption/EncryptAllTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Björn Schießle <schiessle@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Encryption; @@ -26,80 +13,50 @@ use OCP\App\IAppManager; use OCP\Encryption\IEncryptionModule; use OCP\Encryption\IManager; use OCP\IConfig; +use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; class EncryptAllTest extends TestCase { - /** @var \PHPUnit\Framework\MockObject\MockObject | \OCP\IConfig */ - protected $config; - - /** @var \PHPUnit\Framework\MockObject\MockObject | \OCP\Encryption\IManager */ - protected $encryptionManager; - - /** @var \PHPUnit\Framework\MockObject\MockObject | \OCP\App\IAppManager */ - protected $appManager; - - /** @var \PHPUnit\Framework\MockObject\MockObject | \Symfony\Component\Console\Input\InputInterface */ - protected $consoleInput; - - /** @var \PHPUnit\Framework\MockObject\MockObject | \Symfony\Component\Console\Output\OutputInterface */ - protected $consoleOutput; - - /** @var \PHPUnit\Framework\MockObject\MockObject | \Symfony\Component\Console\Helper\QuestionHelper */ - protected $questionHelper; - - /** @var \PHPUnit\Framework\MockObject\MockObject | \OCP\Encryption\IEncryptionModule */ - protected $encryptionModule; + private IConfig&MockObject $config; + private IManager&MockObject $encryptionManager; + private IAppManager&MockObject $appManager; + private InputInterface&MockObject $consoleInput; + private OutputInterface&MockObject $consoleOutput; + private QuestionHelper&MockObject $questionHelper; + private IEncryptionModule&MockObject $encryptionModule; - /** @var EncryptAll */ - protected $command; + private EncryptAll $command; protected function setUp(): void { parent::setUp(); - $this->config = $this->getMockBuilder(IConfig::class) - ->disableOriginalConstructor() - ->getMock(); - $this->encryptionManager = $this->getMockBuilder(IManager::class) - ->disableOriginalConstructor() - ->getMock(); - $this->appManager = $this->getMockBuilder(IAppManager::class) - ->disableOriginalConstructor() - ->getMock(); - $this->encryptionModule = $this->getMockBuilder(IEncryptionModule::class) - ->disableOriginalConstructor() - ->getMock(); - $this->questionHelper = $this->getMockBuilder(QuestionHelper::class) - ->disableOriginalConstructor() - ->getMock(); - $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); + $this->config = $this->createMock(IConfig::class); + $this->encryptionManager = $this->createMock(IManager::class); + $this->appManager = $this->createMock(IAppManager::class); + $this->encryptionModule = $this->createMock(IEncryptionModule::class); + $this->questionHelper = $this->createMock(QuestionHelper::class); + $this->consoleInput = $this->createMock(InputInterface::class); $this->consoleInput->expects($this->any()) ->method('isInteractive') ->willReturn(true); - $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); + $this->consoleOutput = $this->createMock(OutputInterface::class); } - public function testEncryptAll() { + public function testEncryptAll(): void { // trash bin needs to be disabled in order to avoid adding dummy files to the users // trash bin which gets deleted during the encryption process $this->appManager->expects($this->once())->method('disableApp')->with('files_trashbin'); - // enable single user mode to avoid that other user login during encryption - // destructor should disable the single user mode again - $this->config->expects($this->once())->method('getSystemValueBool')->with('maintenance', false)->willReturn(false); - $this->config->expects($this->at(1))->method('setSystemValue')->with('maintenance', true); - $this->config->expects($this->at(2))->method('setSystemValue')->with('maintenance', false); $instance = new EncryptAll($this->encryptionManager, $this->appManager, $this->config, $this->questionHelper); $this->invokePrivate($instance, 'forceMaintenanceAndTrashbin'); $this->invokePrivate($instance, 'resetMaintenanceAndTrashbin'); } - /** - * @dataProvider dataTestExecute - */ - public function testExecute($answer, $askResult) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestExecute')] + public function testExecute($answer, $askResult): void { $command = new EncryptAll($this->encryptionManager, $this->appManager, $this->config, $this->questionHelper); $this->encryptionManager->expects($this->once())->method('isEnabled')->willReturn(true); @@ -118,14 +75,14 @@ class EncryptAllTest extends TestCase { $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function dataTestExecute() { + public static function dataTestExecute(): array { return [ ['y', true], ['Y', true], ['n', false], ['N', false], ['', false] ]; } - public function testExecuteException() { + public function testExecuteException(): void { $this->expectException(\Exception::class); $command = new EncryptAll($this->encryptionManager, $this->appManager, $this->config, $this->questionHelper); diff --git a/tests/Core/Command/Encryption/SetDefaultModuleTest.php b/tests/Core/Command/Encryption/SetDefaultModuleTest.php index 015964e1357..df38d730db3 100644 --- a/tests/Core/Command/Encryption/SetDefaultModuleTest.php +++ b/tests/Core/Command/Encryption/SetDefaultModuleTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Encryption; @@ -57,7 +44,7 @@ class SetDefaultModuleTest extends TestCase { } - public function dataSetDefaultModule() { + public static function dataSetDefaultModule(): array { return [ ['ID0', 'ID0', null, null, 'already'], ['ID0', 'ID1', 'ID1', true, 'info'], @@ -66,7 +53,6 @@ class SetDefaultModuleTest extends TestCase { } /** - * @dataProvider dataSetDefaultModule * * @param string $oldModule * @param string $newModule @@ -74,7 +60,8 @@ class SetDefaultModuleTest extends TestCase { * @param bool $updateSuccess * @param string $expectedString */ - public function testSetDefaultModule($oldModule, $newModule, $updateModule, $updateSuccess, $expectedString) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataSetDefaultModule')] + public function testSetDefaultModule($oldModule, $newModule, $updateModule, $updateSuccess, $expectedString): void { $this->consoleInput->expects($this->once()) ->method('getArgument') ->with('module') @@ -104,7 +91,6 @@ class SetDefaultModuleTest extends TestCase { } /** - * @dataProvider dataSetDefaultModule * * @param string $oldModule * @param string $newModule @@ -112,7 +98,8 @@ class SetDefaultModuleTest extends TestCase { * @param bool $updateSuccess * @param string $expectedString */ - public function testMaintenanceMode($oldModule, $newModule, $updateModule, $updateSuccess, $expectedString) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataSetDefaultModule')] + public function testMaintenanceMode($oldModule, $newModule, $updateModule, $updateSuccess, $expectedString): void { $this->consoleInput->expects($this->never()) ->method('getArgument') ->with('module') @@ -127,13 +114,16 @@ class SetDefaultModuleTest extends TestCase { ->with('maintenance', false) ->willReturn(true); - $this->consoleOutput->expects($this->at(0)) - ->method('writeln') - ->with($this->stringContains('Maintenance mode must be disabled when setting default module,')); - - $this->consoleOutput->expects($this->at(1)) + $calls = [ + 'Maintenance mode must be disabled when setting default module,', + 'in order to load the relevant encryption modules correctly.', + ]; + $this->consoleOutput->expects($this->exactly(2)) ->method('writeln') - ->with($this->stringContains('in order to load the relevant encryption modules correctly.')); + ->willReturnCallback(function ($message) use (&$calls): void { + $expected = array_shift($calls); + $this->assertStringContainsString($expected, $message); + }); self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } diff --git a/tests/Core/Command/Group/AddTest.php b/tests/Core/Command/Group/AddTest.php index bfddee468a4..24f2d823292 100644 --- a/tests/Core/Command/Group/AddTest.php +++ b/tests/Core/Command/Group/AddTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright 2018, Denis Mosolov <denismosolov@gmail.com> - * - * @author Denis Mosolov <denismosolov@gmail.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Afferoq General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\Group; @@ -60,7 +44,7 @@ class AddTest extends TestCase { $this->output = $this->createMock(OutputInterface::class); } - public function testGroupExists() { + public function testGroupExists(): void { $gid = 'myGroup'; $group = $this->createMock(IGroup::class); $this->groupManager->method('get') @@ -76,7 +60,7 @@ class AddTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testAdd() { + public function testAdd(): void { $gid = 'myGroup'; $group = $this->createMock(IGroup::class); $group->method('getGID') diff --git a/tests/Core/Command/Group/AddUserTest.php b/tests/Core/Command/Group/AddUserTest.php index c885365f8c6..68c8cecdba1 100644 --- a/tests/Core/Command/Group/AddUserTest.php +++ b/tests/Core/Command/Group/AddUserTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\Group; @@ -68,7 +52,7 @@ class AddUserTest extends TestCase { $this->output = $this->createMock(OutputInterface::class); } - public function testNoGroup() { + public function testNoGroup(): void { $this->groupManager->method('get') ->with('myGroup') ->willReturn(null); @@ -80,7 +64,7 @@ class AddUserTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testNoUser() { + public function testNoUser(): void { $group = $this->createMock(IGroup::class); $this->groupManager->method('get') ->with('myGroup') @@ -97,7 +81,7 @@ class AddUserTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testAdd() { + public function testAdd(): void { $group = $this->createMock(IGroup::class); $this->groupManager->method('get') ->with('myGroup') diff --git a/tests/Core/Command/Group/DeleteTest.php b/tests/Core/Command/Group/DeleteTest.php index 393f33aea98..289c6a7c322 100644 --- a/tests/Core/Command/Group/DeleteTest.php +++ b/tests/Core/Command/Group/DeleteTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright 2018, Denis Mosolov <denismosolov@gmail.com> - * - * @author Denis Mosolov <denismosolov@gmail.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Afferoq General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\Group; @@ -53,7 +37,7 @@ class DeleteTest extends TestCase { $this->output = $this->createMock(OutputInterface::class); } - public function testDoesNotExists() { + public function testDoesNotExists(): void { $gid = 'myGroup'; $this->input->method('getArgument') ->willReturnCallback(function ($arg) use ($gid) { @@ -75,7 +59,7 @@ class DeleteTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testDeleteAdmin() { + public function testDeleteAdmin(): void { $gid = 'admin'; $this->input->method('getArgument') ->willReturnCallback(function ($arg) use ($gid) { @@ -94,7 +78,7 @@ class DeleteTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testDeleteFailed() { + public function testDeleteFailed(): void { $gid = 'myGroup'; $this->input->method('getArgument') ->willReturnCallback(function ($arg) use ($gid) { @@ -120,7 +104,7 @@ class DeleteTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testDelete() { + public function testDelete(): void { $gid = 'myGroup'; $this->input->method('getArgument') ->willReturnCallback(function ($arg) use ($gid) { diff --git a/tests/Core/Command/Group/InfoTest.php b/tests/Core/Command/Group/InfoTest.php index 3f1cc359799..87f59d2adc4 100644 --- a/tests/Core/Command/Group/InfoTest.php +++ b/tests/Core/Command/Group/InfoTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2021, hosting.de, Johannes Leuker <developers@hosting.de> - * - * @author Johannes Leuker <developers@hosting.de> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Afferoq General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\Group; @@ -49,14 +33,14 @@ class InfoTest extends TestCase { $this->groupManager = $this->createMock(IGroupManager::class); $this->command = $this->getMockBuilder(Info::class) ->setConstructorArgs([$this->groupManager]) - ->setMethods(['writeArrayInOutputFormat']) + ->onlyMethods(['writeArrayInOutputFormat']) ->getMock(); $this->input = $this->createMock(InputInterface::class); $this->output = $this->createMock(OutputInterface::class); } - public function testDoesNotExists() { + public function testDoesNotExists(): void { $gid = 'myGroup'; $this->input->method('getArgument') ->willReturnCallback(function ($arg) use ($gid) { @@ -76,7 +60,7 @@ class InfoTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testInfo() { + public function testInfo(): void { $gid = 'myGroup'; $this->input->method('getArgument') ->willReturnCallback(function ($arg) use ($gid) { diff --git a/tests/Core/Command/Group/ListCommandTest.php b/tests/Core/Command/Group/ListCommandTest.php index f8e750bbe65..aaca772d714 100644 --- a/tests/Core/Command/Group/ListCommandTest.php +++ b/tests/Core/Command/Group/ListCommandTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\Group; @@ -50,14 +34,14 @@ class ListCommandTest extends TestCase { $this->groupManager = $this->createMock(IGroupManager::class); $this->command = $this->getMockBuilder(ListCommand::class) ->setConstructorArgs([$this->groupManager]) - ->setMethods(['writeArrayInOutputFormat']) + ->onlyMethods(['writeArrayInOutputFormat']) ->getMock(); $this->input = $this->createMock(InputInterface::class); $this->output = $this->createMock(OutputInterface::class); } - public function testExecute() { + public function testExecute(): void { $group1 = $this->createMock(IGroup::class); $group1->method('getGID')->willReturn('group1'); $group2 = $this->createMock(IGroup::class); @@ -107,30 +91,35 @@ class ListCommandTest extends TestCase { ->with( $this->equalTo($this->input), $this->equalTo($this->output), - [ - 'group1' => [ - 'user1', - 'user2', - ], - 'group2' => [ - ], - 'group3' => [ - 'user1', - 'user3', + $this->callback( + fn ($iterator) => iterator_to_array($iterator) === [ + 'group1' => [ + 'user1', + 'user2', + ], + 'group2' => [ + ], + 'group3' => [ + 'user1', + 'user3', + ] ] - ] + ) ); $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testInfo() { + public function testInfo(): void { $group1 = $this->createMock(IGroup::class); $group1->method('getGID')->willReturn('group1'); + $group1->method('getDisplayName')->willReturn('Group 1'); $group2 = $this->createMock(IGroup::class); $group2->method('getGID')->willReturn('group2'); + $group2->method('getDisplayName')->willReturn('Group 2'); $group3 = $this->createMock(IGroup::class); $group3->method('getGID')->willReturn('group3'); + $group3->method('getDisplayName')->willReturn('Group 3'); $user = $this->createMock(IUser::class); @@ -183,26 +172,31 @@ class ListCommandTest extends TestCase { ->with( $this->equalTo($this->input), $this->equalTo($this->output), - [ - 'group1' => [ - 'backends' => ['Database'], - 'users' => [ - 'user1', - 'user2', + $this->callback( + fn ($iterator) => iterator_to_array($iterator) === [ + 'group1' => [ + 'displayName' => 'Group 1', + 'backends' => ['Database'], + 'users' => [ + 'user1', + 'user2', + ], ], - ], - 'group2' => [ - 'backends' => ['Database'], - 'users' => [], - ], - 'group3' => [ - 'backends' => ['LDAP'], - 'users' => [ - 'user1', - 'user3', + 'group2' => [ + 'displayName' => 'Group 2', + 'backends' => ['Database'], + 'users' => [], ], + 'group3' => [ + 'displayName' => 'Group 3', + 'backends' => ['LDAP'], + 'users' => [ + 'user1', + 'user3', + ], + ] ] - ] + ) ); $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); diff --git a/tests/Core/Command/Group/RemoveUserTest.php b/tests/Core/Command/Group/RemoveUserTest.php index 470d5965333..74343e77d3f 100644 --- a/tests/Core/Command/Group/RemoveUserTest.php +++ b/tests/Core/Command/Group/RemoveUserTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\Group; @@ -68,7 +52,7 @@ class RemoveUserTest extends TestCase { $this->output = $this->createMock(OutputInterface::class); } - public function testNoGroup() { + public function testNoGroup(): void { $this->groupManager->method('get') ->with('myGroup') ->willReturn(null); @@ -80,7 +64,7 @@ class RemoveUserTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testNoUser() { + public function testNoUser(): void { $group = $this->createMock(IGroup::class); $this->groupManager->method('get') ->with('myGroup') @@ -97,7 +81,7 @@ class RemoveUserTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testAdd() { + public function testAdd(): void { $group = $this->createMock(IGroup::class); $this->groupManager->method('get') ->with('myGroup') diff --git a/tests/Core/Command/Log/FileTest.php b/tests/Core/Command/Log/FileTest.php index 103888de287..1aaf398b875 100644 --- a/tests/Core/Command/Log/FileTest.php +++ b/tests/Core/Command/Log/FileTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Robin McCorkell <rmccorkell@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Log; @@ -50,7 +37,7 @@ class FileTest extends TestCase { $this->command = new File($config); } - public function testEnable() { + public function testEnable(): void { $this->config->method('getSystemValue')->willReturnArgument(1); $this->consoleInput->method('getOption') ->willReturnMap([ @@ -63,7 +50,7 @@ class FileTest extends TestCase { self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function testChangeFile() { + public function testChangeFile(): void { $this->config->method('getSystemValue')->willReturnArgument(1); $this->consoleInput->method('getOption') ->willReturnMap([ @@ -76,7 +63,7 @@ class FileTest extends TestCase { self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function changeRotateSizeProvider() { + public static function changeRotateSizeProvider(): array { return [ ['42', 42], ['0', 0], @@ -85,10 +72,8 @@ class FileTest extends TestCase { ]; } - /** - * @dataProvider changeRotateSizeProvider - */ - public function testChangeRotateSize($optionValue, $configValue) { + #[\PHPUnit\Framework\Attributes\DataProvider('changeRotateSizeProvider')] + public function testChangeRotateSize($optionValue, $configValue): void { $this->config->method('getSystemValue')->willReturnArgument(1); $this->consoleInput->method('getOption') ->willReturnMap([ @@ -101,24 +86,26 @@ class FileTest extends TestCase { self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function testGetConfiguration() { + public function testGetConfiguration(): void { $this->config->method('getSystemValue') ->willReturnMap([ ['log_type', 'file', 'log_type_value'], - ['datadirectory', \OC::$SERVERROOT.'/data', '/data/directory/'], + ['datadirectory', \OC::$SERVERROOT . '/data', '/data/directory/'], ['logfile', '/data/directory/nextcloud.log', '/var/log/nextcloud.log'], ['log_rotate_size', 100 * 1024 * 1024, 5 * 1024 * 1024], ]); - $this->consoleOutput->expects($this->at(0)) - ->method('writeln') - ->with('Log backend file: disabled'); - $this->consoleOutput->expects($this->at(1)) - ->method('writeln') - ->with('Log file: /var/log/nextcloud.log'); - $this->consoleOutput->expects($this->at(2)) + $calls = [ + ['Log backend file: disabled'], + ['Log file: /var/log/nextcloud.log'], + ['Rotate at: 5 MB'], + ]; + $this->consoleOutput->expects($this->exactly(3)) ->method('writeln') - ->with('Rotate at: 5 MB'); + ->willReturnCallback(function (string $message) use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected[0], $message); + }); self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } diff --git a/tests/Core/Command/Log/ManageTest.php b/tests/Core/Command/Log/ManageTest.php index 6683291a9b8..8b307048719 100644 --- a/tests/Core/Command/Log/ManageTest.php +++ b/tests/Core/Command/Log/ManageTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Robin McCorkell <rmccorkell@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Log; @@ -50,7 +37,7 @@ class ManageTest extends TestCase { $this->command = new Manage($config); } - public function testChangeBackend() { + public function testChangeBackend(): void { $this->consoleInput->method('getOption') ->willReturnMap([ ['backend', 'syslog'] @@ -62,7 +49,7 @@ class ManageTest extends TestCase { self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function testChangeLevel() { + public function testChangeLevel(): void { $this->consoleInput->method('getOption') ->willReturnMap([ ['level', 'debug'] @@ -74,7 +61,7 @@ class ManageTest extends TestCase { self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function testChangeTimezone() { + public function testChangeTimezone(): void { $this->consoleInput->method('getOption') ->willReturnMap([ ['timezone', 'UTC'] @@ -87,21 +74,21 @@ class ManageTest extends TestCase { } - public function testValidateBackend() { + public function testValidateBackend(): void { $this->expectException(\InvalidArgumentException::class); self::invokePrivate($this->command, 'validateBackend', ['notabackend']); } - public function testValidateTimezone() { + public function testValidateTimezone(): void { $this->expectException(\Exception::class); // this might need to be changed when humanity colonises Mars self::invokePrivate($this->command, 'validateTimezone', ['Mars/OlympusMons']); } - public function convertLevelStringProvider() { + public static function dataConvertLevelString(): array { return [ ['dEbug', 0], ['inFO', 1], @@ -113,23 +100,21 @@ class ManageTest extends TestCase { ]; } - /** - * @dataProvider convertLevelStringProvider - */ - public function testConvertLevelString($levelString, $expectedInt) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataConvertLevelString')] + public function testConvertLevelString(string $levelString, int $expectedInt): void { $this->assertEquals($expectedInt, self::invokePrivate($this->command, 'convertLevelString', [$levelString]) ); } - public function testConvertLevelStringInvalid() { + public function testConvertLevelStringInvalid(): void { $this->expectException(\InvalidArgumentException::class); self::invokePrivate($this->command, 'convertLevelString', ['abc']); } - public function convertLevelNumberProvider() { + public static function dataConvertLevelNumber(): array { return [ [0, 'Debug'], [1, 'Info'], @@ -139,45 +124,40 @@ class ManageTest extends TestCase { ]; } - /** - * @dataProvider convertLevelNumberProvider - */ - public function testConvertLevelNumber($levelNum, $expectedString) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataConvertLevelNumber')] + public function testConvertLevelNumber(int $levelNum, string $expectedString): void { $this->assertEquals($expectedString, self::invokePrivate($this->command, 'convertLevelNumber', [$levelNum]) ); } - public function testConvertLevelNumberInvalid() { + public function testConvertLevelNumberInvalid(): void { $this->expectException(\InvalidArgumentException::class); self::invokePrivate($this->command, 'convertLevelNumber', [11]); } - public function testGetConfiguration() { - $this->config->expects($this->at(0)) - ->method('getSystemValue') - ->with('log_type', 'file') - ->willReturn('log_type_value'); - $this->config->expects($this->at(1)) + public function testGetConfiguration(): void { + $this->config->expects($this->exactly(3)) ->method('getSystemValue') - ->with('loglevel', 2) - ->willReturn(0); - $this->config->expects($this->at(2)) - ->method('getSystemValue') - ->with('logtimezone', 'UTC') - ->willReturn('logtimezone_value'); + ->willReturnMap([ + ['log_type', 'file', 'log_type_value'], + ['loglevel', 2, 0], + ['logtimezone', 'UTC', 'logtimezone_value'], + ]); - $this->consoleOutput->expects($this->at(0)) - ->method('writeln') - ->with('Enabled logging backend: log_type_value'); - $this->consoleOutput->expects($this->at(1)) - ->method('writeln') - ->with('Log level: Debug (0)'); - $this->consoleOutput->expects($this->at(2)) + $calls = [ + ['Enabled logging backend: log_type_value'], + ['Log level: Debug (0)'], + ['Log timezone: logtimezone_value'], + ]; + $this->consoleOutput->expects($this->exactly(3)) ->method('writeln') - ->with('Log timezone: logtimezone_value'); + ->willReturnCallback(function (string $message) use (&$calls): void { + $call = array_shift($calls); + $this->assertStringContainsString($call[0], $message); + }); self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } diff --git a/tests/Core/Command/Maintenance/DataFingerprintTest.php b/tests/Core/Command/Maintenance/DataFingerprintTest.php index 185a8d1576a..99004a7a5f5 100644 --- a/tests/Core/Command/Maintenance/DataFingerprintTest.php +++ b/tests/Core/Command/Maintenance/DataFingerprintTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Roeland Jago Douma <rullzer@owncloud.com> - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Maintenance; @@ -49,11 +36,11 @@ class DataFingerprintTest extends TestCase { $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); - /** @var \OCP\IConfig $config */ + /** @var IConfig $config */ $this->command = new DataFingerprint($this->config, $this->timeFactory); } - public function testSetFingerPrint() { + public function testSetFingerPrint(): void { $this->timeFactory->expects($this->once()) ->method('getTime') ->willReturn(42); diff --git a/tests/Core/Command/Maintenance/Mimetype/UpdateDBTest.php b/tests/Core/Command/Maintenance/Mimetype/UpdateDBTest.php index bd08a5348a2..b85dcf87bbc 100644 --- a/tests/Core/Command/Maintenance/Mimetype/UpdateDBTest.php +++ b/tests/Core/Command/Maintenance/Mimetype/UpdateDBTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Robin McCorkell <rmccorkell@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\Maintenance\Mimetype; @@ -47,20 +34,15 @@ class UpdateDBTest extends TestCase { protected function setUp(): void { parent::setUp(); - $this->detector = $this->getMockBuilder(Detection::class) - ->disableOriginalConstructor() - ->getMock(); - $this->loader = $this->getMockBuilder(Loader::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); - $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); + $this->detector = $this->createMock(Detection::class); + $this->loader = $this->createMock(Loader::class); + $this->consoleInput = $this->createMock(InputInterface::class); + $this->consoleOutput = $this->createMock(OutputInterface::class); $this->command = new UpdateDB($this->detector, $this->loader); } - public function testNoop() { + public function testNoop(): void { $this->consoleInput->method('getOption') ->with('repair-filecache') ->willReturn(false); @@ -78,17 +60,21 @@ class UpdateDBTest extends TestCase { $this->loader->expects($this->never()) ->method('updateFilecache'); - $this->consoleOutput->expects($this->at(0)) - ->method('writeln') - ->with('Added 0 new mimetypes'); - $this->consoleOutput->expects($this->at(1)) + $calls = [ + 'Added 0 new mimetypes', + 'Updated 0 filecache rows', + ]; + $this->consoleOutput->expects($this->exactly(2)) ->method('writeln') - ->with('Updated 0 filecache rows'); + ->willReturnCallback(function ($message) use (&$calls): void { + $expected = array_shift($calls); + $this->assertStringContainsString($expected, $message); + }); self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function testAddMimetype() { + public function testAddMimetype(): void { $this->consoleInput->method('getOption') ->with('repair-filecache') ->willReturn(false); @@ -117,24 +103,23 @@ class UpdateDBTest extends TestCase { ->with('new', 2) ->willReturn(3); - $this->consoleOutput->expects($this->at(0)) - ->method('writeln') - ->with('Added mimetype "testing/newmimetype" to database'); - $this->consoleOutput->expects($this->at(1)) - ->method('writeln') - ->with('Updated 3 filecache rows for mimetype "testing/newmimetype"'); - - $this->consoleOutput->expects($this->at(2)) - ->method('writeln') - ->with('Added 1 new mimetypes'); - $this->consoleOutput->expects($this->at(3)) + $calls = [ + 'Added mimetype "testing/newmimetype" to database', + 'Updated 3 filecache rows for mimetype "testing/newmimetype"', + 'Added 1 new mimetypes', + 'Updated 3 filecache rows', + ]; + $this->consoleOutput->expects($this->exactly(4)) ->method('writeln') - ->with('Updated 3 filecache rows'); + ->willReturnCallback(function ($message) use (&$calls): void { + $expected = array_shift($calls); + $this->assertStringContainsString($expected, $message); + }); self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function testSkipComments() { + public function testSkipComments(): void { $this->detector->expects($this->once()) ->method('getAllMappings') ->willReturn([ @@ -146,7 +131,7 @@ class UpdateDBTest extends TestCase { self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function testRepairFilecache() { + public function testRepairFilecache(): void { $this->consoleInput->method('getOption') ->with('repair-filecache') ->willReturn(true); @@ -172,16 +157,17 @@ class UpdateDBTest extends TestCase { ->with('ext', 1) ->willReturn(3); - $this->consoleOutput->expects($this->at(0)) - ->method('writeln') - ->with('Updated 3 filecache rows for mimetype "testing/existingmimetype"'); - - $this->consoleOutput->expects($this->at(1)) - ->method('writeln') - ->with('Added 0 new mimetypes'); - $this->consoleOutput->expects($this->at(2)) + $calls = [ + 'Updated 3 filecache rows for mimetype "testing/existingmimetype"', + 'Added 0 new mimetypes', + 'Updated 3 filecache rows', + ]; + $this->consoleOutput->expects($this->exactly(3)) ->method('writeln') - ->with('Updated 3 filecache rows'); + ->willReturnCallback(function ($message) use (&$calls): void { + $expected = array_shift($calls); + $this->assertStringContainsString($expected, $message); + }); self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } diff --git a/tests/Core/Command/Maintenance/ModeTest.php b/tests/Core/Command/Maintenance/ModeTest.php index 1e8af354d50..5a9a90b0197 100644 --- a/tests/Core/Command/Maintenance/ModeTest.php +++ b/tests/Core/Command/Maintenance/ModeTest.php @@ -1,5 +1,9 @@ <?php +/** + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ namespace Tests\Core\Command\Maintenance; use OC\Core\Command\Maintenance\Mode; @@ -64,7 +68,7 @@ class ModeTest extends TestCase { * * @return array */ - public function getExecuteTestData(): array { + public static function getExecuteTestData(): array { return [ 'off -> on' => [ 'on', // command option @@ -108,20 +112,20 @@ class ModeTest extends TestCase { /** * Asserts that execute works as expected. * - * @dataProvider getExecuteTestData * @param string $option The command option. * @param bool $currentMaintenanceState The current maintenance state. * @param null|bool $expectedMaintenanceState - * The expected maintenance state. Null for no change. + * The expected maintenance state. Null for no change. * @param string $expectedOutput The expected command output. * @throws \Exception */ + #[\PHPUnit\Framework\Attributes\DataProvider('getExecuteTestData')] public function testExecute( string $option, bool $currentMaintenanceState, $expectedMaintenanceState, - string $expectedOutput - ) { + string $expectedOutput, + ): void { $this->config->expects($this->any()) ->method('getSystemValueBool') ->willReturn($currentMaintenanceState); diff --git a/tests/Core/Command/Maintenance/UpdateTheme.php b/tests/Core/Command/Maintenance/UpdateTheme.php index bf460b44d4e..9c9a2b903a7 100644 --- a/tests/Core/Command/Maintenance/UpdateTheme.php +++ b/tests/Core/Command/Maintenance/UpdateTheme.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2017 Julius Härtl <jus@bitgrid.net> - * - * @author Julius Härtl <jus@bitgrid.net> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Command\Maintenance; @@ -59,7 +43,7 @@ class UpdateThemeTest extends TestCase { $this->command = new UpdateTheme($this->detector, $this->cacheFactory); } - public function testThemeUpdate() { + public function testThemeUpdate(): void { $this->consoleInput->method('getOption') ->with('maintenance:theme:update') ->willReturn(true); diff --git a/tests/Core/Command/Preview/CleanupTest.php b/tests/Core/Command/Preview/CleanupTest.php new file mode 100644 index 00000000000..e4a83246e5b --- /dev/null +++ b/tests/Core/Command/Preview/CleanupTest.php @@ -0,0 +1,175 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace Core\Command\Preview; + +use OC\Core\Command\Preview\Cleanup; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Test\TestCase; + +class CleanupTest extends TestCase { + private IRootFolder&MockObject $rootFolder; + private LoggerInterface&MockObject $logger; + private InputInterface&MockObject $input; + private OutputInterface&MockObject $output; + private Cleanup $repair; + + protected function setUp(): void { + parent::setUp(); + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->repair = new Cleanup( + $this->rootFolder, + $this->logger, + ); + + $this->input = $this->createMock(InputInterface::class); + $this->output = $this->createMock(OutputInterface::class); + } + + public function testCleanup(): void { + $previewFolder = $this->createMock(Folder::class); + $previewFolder->expects($this->once()) + ->method('isDeletable') + ->willReturn(true); + + $previewFolder->expects($this->once()) + ->method('delete'); + + $appDataFolder = $this->createMock(Folder::class); + $appDataFolder->expects($this->once())->method('get')->with('preview')->willReturn($previewFolder); + $appDataFolder->expects($this->once())->method('newFolder')->with('preview'); + + $this->rootFolder->expects($this->once()) + ->method('getAppDataDirectoryName') + ->willReturn('appdata_some_id'); + + $this->rootFolder->expects($this->once()) + ->method('get') + ->with('appdata_some_id') + ->willReturn($appDataFolder); + + $this->output->expects($this->exactly(3))->method('writeln') + ->with(self::callback(function (string $message): bool { + static $i = 0; + return match (++$i) { + 1 => $message === 'Preview folder deleted', + 2 => $message === 'Preview folder recreated', + 3 => $message === 'Previews removed' + }; + })); + + $this->assertEquals(0, $this->repair->run($this->input, $this->output)); + } + + public function testCleanupWhenNotDeletable(): void { + $previewFolder = $this->createMock(Folder::class); + $previewFolder->expects($this->once()) + ->method('isDeletable') + ->willReturn(false); + + $previewFolder->expects($this->never()) + ->method('delete'); + + $appDataFolder = $this->createMock(Folder::class); + $appDataFolder->expects($this->once())->method('get')->with('preview')->willReturn($previewFolder); + $appDataFolder->expects($this->never())->method('newFolder')->with('preview'); + + $this->rootFolder->expects($this->once()) + ->method('getAppDataDirectoryName') + ->willReturn('appdata_some_id'); + + $this->rootFolder->expects($this->once()) + ->method('get') + ->with('appdata_some_id') + ->willReturn($appDataFolder); + + $this->logger->expects($this->once())->method('error')->with("Previews can't be removed: preview folder isn't deletable"); + $this->output->expects($this->once())->method('writeln')->with("Previews can't be removed: preview folder isn't deletable"); + + $this->assertEquals(1, $this->repair->run($this->input, $this->output)); + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataForTestCleanupWithDeleteException')] + public function testCleanupWithDeleteException(string $exceptionClass, string $errorMessage): void { + $previewFolder = $this->createMock(Folder::class); + $previewFolder->expects($this->once()) + ->method('isDeletable') + ->willReturn(true); + + $previewFolder->expects($this->once()) + ->method('delete') + ->willThrowException(new $exceptionClass()); + + $appDataFolder = $this->createMock(Folder::class); + $appDataFolder->expects($this->once())->method('get')->with('preview')->willReturn($previewFolder); + $appDataFolder->expects($this->never())->method('newFolder')->with('preview'); + + $this->rootFolder->expects($this->once()) + ->method('getAppDataDirectoryName') + ->willReturn('appdata_some_id'); + + $this->rootFolder->expects($this->once()) + ->method('get') + ->with('appdata_some_id') + ->willReturn($appDataFolder); + + $this->logger->expects($this->once())->method('error')->with($errorMessage); + $this->output->expects($this->once())->method('writeln')->with($errorMessage); + + $this->assertEquals(1, $this->repair->run($this->input, $this->output)); + } + + public static function dataForTestCleanupWithDeleteException(): array { + return [ + [NotFoundException::class, "Previews weren't deleted: preview folder was not found while deleting it"], + [NotPermittedException::class, "Previews weren't deleted: you don't have the permission to delete preview folder"], + ]; + } + + public function testCleanupWithCreateException(): void { + $previewFolder = $this->createMock(Folder::class); + $previewFolder->expects($this->once()) + ->method('isDeletable') + ->willReturn(true); + + $previewFolder->expects($this->once()) + ->method('delete'); + + $appDataFolder = $this->createMock(Folder::class); + $appDataFolder->expects($this->once())->method('get')->with('preview')->willReturn($previewFolder); + $appDataFolder->expects($this->once())->method('newFolder')->with('preview')->willThrowException(new NotPermittedException()); + + $this->rootFolder->expects($this->once()) + ->method('getAppDataDirectoryName') + ->willReturn('appdata_some_id'); + + $this->rootFolder->expects($this->once()) + ->method('get') + ->with('appdata_some_id') + ->willReturn($appDataFolder); + + $this->output->expects($this->exactly(2))->method('writeln') + ->with(self::callback(function (string $message): bool { + static $i = 0; + return match (++$i) { + 1 => $message === 'Preview folder deleted', + 2 => $message === "Preview folder was deleted, but you don't have the permission to create preview folder", + }; + })); + + $this->logger->expects($this->once())->method('error')->with("Preview folder was deleted, but you don't have the permission to create preview folder"); + + $this->assertEquals(1, $this->repair->run($this->input, $this->output)); + } +} diff --git a/tests/Core/Command/Preview/RepairTest.php b/tests/Core/Command/Preview/RepairTest.php index d235c0d0aea..9b9cde6dd95 100644 --- a/tests/Core/Command/Preview/RepairTest.php +++ b/tests/Core/Command/Preview/RepairTest.php @@ -1,5 +1,9 @@ <?php +/** + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ namespace Tests\Core\Command\Preview; use bantu\IniGetWrapper\IniGetWrapper; @@ -10,11 +14,12 @@ use OCP\Files\Node; use OCP\IConfig; use OCP\Lock\ILockingProvider; use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; -use Psr\Log\LoggerInterface; class RepairTest extends TestCase { /** @var IConfig|MockObject */ @@ -51,8 +56,7 @@ class RepairTest extends TestCase { $this->iniGetWrapper, $this->createMock(ILockingProvider::class) ); - $this->input = $this->getMockBuilder(InputInterface::class) - ->getMock(); + $this->input = $this->createMock(InputInterface::class); $this->input->expects($this->any()) ->method('getOption') ->willReturnCallback(function ($parameter) { @@ -61,16 +65,14 @@ class RepairTest extends TestCase { } return null; }); - $this->output = $this->getMockBuilder(OutputInterface::class) - ->setMethods(['section', 'writeln', 'write', 'setVerbosity', 'getVerbosity', 'isQuiet', 'isVerbose', 'isVeryVerbose', 'isDebug', 'setDecorated', 'isDecorated', 'setFormatter', 'getFormatter']) + $this->output = $this->getMockBuilder(ConsoleOutput::class) + ->onlyMethods(['section', 'writeln', 'getFormatter']) ->getMock(); $self = $this; - $this->output->expects($this->any()) - ->method('section') - ->willReturn($this->output); /* We need format method to return a string */ $outputFormatter = $this->createMock(OutputFormatterInterface::class); + $outputFormatter->method('isDecorated')->willReturn(false); $outputFormatter->method('format')->willReturnArgument(0); $this->output->expects($this->any()) @@ -78,12 +80,12 @@ class RepairTest extends TestCase { ->willReturn($outputFormatter); $this->output->expects($this->any()) ->method('writeln') - ->willReturnCallback(function ($line) use ($self) { + ->willReturnCallback(function ($line) use ($self): void { $self->outputLines .= $line . "\n"; }); } - public function emptyTestDataProvider() { + public static function dataEmptyTest(): array { /** directoryNames, expectedOutput */ return [ [ @@ -109,10 +111,8 @@ class RepairTest extends TestCase { ]; } - /** - * @dataProvider emptyTestDataProvider - */ - public function testEmptyExecute($directoryNames, $expectedOutput) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataEmptyTest')] + public function testEmptyExecute($directoryNames, $expectedOutput): void { $previewFolder = $this->getMockBuilder(Folder::class) ->getMock(); $directories = array_map(function ($element) { @@ -141,9 +141,9 @@ class RepairTest extends TestCase { $previewFolder->expects($this->once()) ->method('getDirectoryListing') ->willReturn($directories); - $this->rootFolder->expects($this->at(0)) + $this->rootFolder->expects($this->once()) ->method('get') - ->with("appdata_/preview") + ->with('appdata_/preview') ->willReturn($previewFolder); $this->repair->run($this->input, $this->output); diff --git a/tests/Core/Command/SystemTag/AddTest.php b/tests/Core/Command/SystemTag/AddTest.php index 93a79e1e1a9..5f3c7174758 100644 --- a/tests/Core/Command/SystemTag/AddTest.php +++ b/tests/Core/Command/SystemTag/AddTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2021, hosting.de, Johannes Leuker <developers@hosting.de> - * - * @author Johannes Leuker <developers@hosting.de> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\SystemTag; @@ -50,14 +34,14 @@ class AddTest extends TestCase { $this->systemTagManager = $this->createMock(ISystemTagManager::class); $this->command = $this->getMockBuilder(Add::class) ->setConstructorArgs([$this->systemTagManager]) - ->setMethods(['writeArrayInOutputFormat']) + ->onlyMethods(['writeArrayInOutputFormat']) ->getMock(); $this->input = $this->createMock(InputInterface::class); $this->output = $this->createMock(OutputInterface::class); } - public function testExecute() { + public function testExecute(): void { $tagId = '42'; $tagName = 'wichtig'; $tagAccess = 'public'; @@ -99,7 +83,7 @@ class AddTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testAlreadyExists() { + public function testAlreadyExists(): void { $tagId = '42'; $tagName = 'wichtig'; $tagAccess = 'public'; @@ -110,9 +94,9 @@ class AddTest extends TestCase { $tag->method('getAccessLevel')->willReturn(ISystemTag::ACCESS_LEVEL_PUBLIC); $this->systemTagManager->method('createTag') - ->willReturnCallback(function ($tagName, $userVisible, $userAssignable) { + ->willReturnCallback(function ($tagName, $userVisible, $userAssignable): void { throw new TagAlreadyExistsException( - 'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') already exists' + 'Tag ("' . $tagName . '", ' . $userVisible . ', ' . $userAssignable . ') already exists' ); }); diff --git a/tests/Core/Command/SystemTag/DeleteTest.php b/tests/Core/Command/SystemTag/DeleteTest.php index 16c0c9e7b04..bf756311000 100644 --- a/tests/Core/Command/SystemTag/DeleteTest.php +++ b/tests/Core/Command/SystemTag/DeleteTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2021, hosting.de, Johannes Leuker <developers@hosting.de> - * - * @author Johannes Leuker <developers@hosting.de> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\SystemTag; @@ -49,14 +33,14 @@ class DeleteTest extends TestCase { $this->systemTagManager = $this->createMock(ISystemTagManager::class); $this->command = $this->getMockBuilder(Delete::class) ->setConstructorArgs([$this->systemTagManager]) - ->setMethods(['writeArrayInOutputFormat']) + ->onlyMethods(['writeArrayInOutputFormat']) ->getMock(); $this->input = $this->createMock(InputInterface::class); $this->output = $this->createMock(OutputInterface::class); } - public function testExecute() { + public function testExecute(): void { $tagId = 69; $this->input->method('getArgument') @@ -74,7 +58,7 @@ class DeleteTest extends TestCase { $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testNotFound() { + public function testNotFound(): void { $tagId = 69; $this->input->method('getArgument') @@ -86,7 +70,7 @@ class DeleteTest extends TestCase { }); $this->systemTagManager->method('deleteTags') - ->willReturnCallback(function ($tagId) { + ->willReturnCallback(function ($tagId): void { throw new TagNotFoundException(); }); diff --git a/tests/Core/Command/SystemTag/EditTest.php b/tests/Core/Command/SystemTag/EditTest.php index a5340cf6b53..b22151e3608 100644 --- a/tests/Core/Command/SystemTag/EditTest.php +++ b/tests/Core/Command/SystemTag/EditTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2021, hosting.de, Johannes Leuker <developers@hosting.de> - * - * @author Johannes Leuker <developers@hosting.de> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\SystemTag; @@ -50,14 +34,14 @@ class EditTest extends TestCase { $this->systemTagManager = $this->createMock(ISystemTagManager::class); $this->command = $this->getMockBuilder(Edit::class) ->setConstructorArgs([$this->systemTagManager]) - ->setMethods(['writeArrayInOutputFormat']) + ->onlyMethods(['writeArrayInOutputFormat']) ->getMock(); $this->input = $this->createMock(InputInterface::class); $this->output = $this->createMock(OutputInterface::class); } - public function testExecute() { + public function testExecute(): void { $tagId = '5'; $tagName = 'unwichtige Dateien'; $newTagName = 'moderat wichtige Dateien'; @@ -98,19 +82,20 @@ class EditTest extends TestCase { $tagId, $newTagName, $newTagUserVisible, - $newTagUserAssignable + $newTagUserAssignable, + '' ); $this->output->expects($this->once()) ->method('writeln') ->with( - '<info>Tag updated ("'.$newTagName.'", '.$newTagUserVisible.', '.$newTagUserAssignable.')</info>' + '<info>Tag updated ("' . $newTagName . '", ' . json_encode($newTagUserVisible) . ', ' . json_encode($newTagUserAssignable) . ', "")</info>' ); $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testAlreadyExists() { + public function testAlreadyExists(): void { $tagId = '5'; $tagName = 'unwichtige Dateien'; $tagUserVisible = false; @@ -150,9 +135,9 @@ class EditTest extends TestCase { }); $this->systemTagManager->method('updateTag') - ->willReturnCallback(function ($tagId, $tagName, $userVisible, $userAssignable) { + ->willReturnCallback(function ($tagId, $tagName, $userVisible, $userAssignable): void { throw new TagAlreadyExistsException( - 'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') already exists' + 'Tag ("' . $tagName . '", ' . $userVisible . ', ' . $userAssignable . ') already exists' ); }); @@ -162,19 +147,20 @@ class EditTest extends TestCase { $tagId, $newTagName, $newTagUserVisible, - $newTagUserAssignable + $newTagUserAssignable, + '' ); $this->output->expects($this->once()) ->method('writeln') ->with( - '<error>Tag ("' . $newTagName . '", '. $newTagUserVisible . ', ' . $newTagUserAssignable . ') already exists</error>' + '<error>Tag ("' . $newTagName . '", ' . $newTagUserVisible . ', ' . $newTagUserAssignable . ') already exists</error>' ); $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testNotFound() { + public function testNotFound(): void { $tagId = '404'; $this->input->method('getArgument') @@ -186,8 +172,8 @@ class EditTest extends TestCase { }); $this->systemTagManager->method('getTagsByIds') - ->with($tagId) - ->willReturn([]); + ->with($tagId) + ->willReturn([]); $this->output->expects($this->once()) ->method('writeln') diff --git a/tests/Core/Command/SystemTag/ListCommandTest.php b/tests/Core/Command/SystemTag/ListCommandTest.php index 6488e130947..e1ff8290633 100644 --- a/tests/Core/Command/SystemTag/ListCommandTest.php +++ b/tests/Core/Command/SystemTag/ListCommandTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2021, hosting.de, Johannes Leuker <developers@hosting.de> - * - * @author Johannes Leuker <developers@hosting.de> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\SystemTag; @@ -49,14 +33,14 @@ class ListCommandTest extends TestCase { $this->systemTagManager = $this->createMock(ISystemTagManager::class); $this->command = $this->getMockBuilder(ListCommand::class) ->setConstructorArgs([$this->systemTagManager]) - ->setMethods(['writeArrayInOutputFormat']) + ->onlyMethods(['writeArrayInOutputFormat']) ->getMock(); $this->input = $this->createMock(InputInterface::class); $this->output = $this->createMock(OutputInterface::class); } - public function testExecute() { + public function testExecute(): void { $tag1 = $this->createMock(ISystemTag::class); $tag1->method('getId')->willReturn('1'); $tag1->method('getName')->willReturn('public_tag'); diff --git a/tests/Core/Command/TwoFactorAuth/CleanupTest.php b/tests/Core/Command/TwoFactorAuth/CleanupTest.php index b23e9c9b4c4..1d4731ff0c2 100644 --- a/tests/Core/Command/TwoFactorAuth/CleanupTest.php +++ b/tests/Core/Command/TwoFactorAuth/CleanupTest.php @@ -3,31 +3,15 @@ declare(strict_types=1); /** - * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Core\Command\TwoFactorAuth; use OC\Core\Command\TwoFactorAuth\Cleanup; use OCP\Authentication\TwoFactorAuth\IRegistry; +use OCP\IUserManager; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Console\Tester\CommandTester; use Test\TestCase; @@ -36,6 +20,9 @@ class CleanupTest extends TestCase { /** @var IRegistry|MockObject */ private $registry; + /** @var IUserManager|MockObject */ + private $userManager; + /** @var CommandTester */ private $cmd; @@ -43,12 +30,13 @@ class CleanupTest extends TestCase { parent::setUp(); $this->registry = $this->createMock(IRegistry::class); + $this->userManager = $this->createMock(IUserManager::class); - $cmd = new Cleanup($this->registry); + $cmd = new Cleanup($this->registry, $this->userManager); $this->cmd = new CommandTester($cmd); } - public function testCleanup() { + public function testCleanup(): void { $this->registry->expects($this->once()) ->method('cleanUp') ->with('u2f'); @@ -59,6 +47,6 @@ class CleanupTest extends TestCase { $this->assertEquals(0, $rc); $output = $this->cmd->getDisplay(); - $this->assertStringContainsString("All user-provider associations for provider u2f have been removed", $output); + $this->assertStringContainsString('All user-provider associations for provider u2f have been removed', $output); } } diff --git a/tests/Core/Command/TwoFactorAuth/DisableTest.php b/tests/Core/Command/TwoFactorAuth/DisableTest.php index 35b810c637f..ab6b10f8964 100644 --- a/tests/Core/Command/TwoFactorAuth/DisableTest.php +++ b/tests/Core/Command/TwoFactorAuth/DisableTest.php @@ -3,25 +3,8 @@ declare(strict_types=1); /** - * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\TwoFactorAuth; @@ -54,7 +37,7 @@ class DisableTest extends TestCase { $this->command = new CommandTester($cmd); } - public function testInvalidUID() { + public function testInvalidUID(): void { $this->userManager->expects($this->once()) ->method('get') ->with('nope') @@ -66,10 +49,10 @@ class DisableTest extends TestCase { ]); $this->assertEquals(1, $rc); - $this->assertStringContainsString("Invalid UID", $this->command->getDisplay()); + $this->assertStringContainsString('Invalid UID', $this->command->getDisplay()); } - public function testEnableNotSupported() { + public function testEnableNotSupported(): void { $user = $this->createMock(IUser::class); $this->userManager->expects($this->once()) ->method('get') @@ -86,10 +69,10 @@ class DisableTest extends TestCase { ]); $this->assertEquals(2, $rc); - $this->assertStringContainsString("The provider does not support this operation", $this->command->getDisplay()); + $this->assertStringContainsString('The provider does not support this operation', $this->command->getDisplay()); } - public function testEnabled() { + public function testEnabled(): void { $user = $this->createMock(IUser::class); $this->userManager->expects($this->once()) ->method('get') @@ -106,6 +89,6 @@ class DisableTest extends TestCase { ]); $this->assertEquals(0, $rc); - $this->assertStringContainsString("Two-factor provider totp disabled for user ricky", $this->command->getDisplay()); + $this->assertStringContainsString('Two-factor provider totp disabled for user ricky', $this->command->getDisplay()); } } diff --git a/tests/Core/Command/TwoFactorAuth/EnableTest.php b/tests/Core/Command/TwoFactorAuth/EnableTest.php index 0e26bcb9578..7c34d6692c5 100644 --- a/tests/Core/Command/TwoFactorAuth/EnableTest.php +++ b/tests/Core/Command/TwoFactorAuth/EnableTest.php @@ -3,25 +3,8 @@ declare(strict_types=1); /** - * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Command\TwoFactorAuth; @@ -54,7 +37,7 @@ class EnableTest extends TestCase { $this->command = new CommandTester($cmd); } - public function testInvalidUID() { + public function testInvalidUID(): void { $this->userManager->expects($this->once()) ->method('get') ->with('nope') @@ -66,10 +49,10 @@ class EnableTest extends TestCase { ]); $this->assertEquals(1, $rc); - $this->assertStringContainsString("Invalid UID", $this->command->getDisplay()); + $this->assertStringContainsString('Invalid UID', $this->command->getDisplay()); } - public function testEnableNotSupported() { + public function testEnableNotSupported(): void { $user = $this->createMock(IUser::class); $this->userManager->expects($this->once()) ->method('get') @@ -86,10 +69,10 @@ class EnableTest extends TestCase { ]); $this->assertEquals(2, $rc); - $this->assertStringContainsString("The provider does not support this operation", $this->command->getDisplay()); + $this->assertStringContainsString('The provider does not support this operation', $this->command->getDisplay()); } - public function testEnabled() { + public function testEnabled(): void { $user = $this->createMock(IUser::class); $this->userManager->expects($this->once()) ->method('get') @@ -106,6 +89,6 @@ class EnableTest extends TestCase { ]); $this->assertEquals(0, $rc); - $this->assertStringContainsString("Two-factor provider totp enabled for user belle", $this->command->getDisplay()); + $this->assertStringContainsString('Two-factor provider totp enabled for user belle', $this->command->getDisplay()); } } diff --git a/tests/Core/Command/TwoFactorAuth/EnforceTest.php b/tests/Core/Command/TwoFactorAuth/EnforceTest.php index 194e16e8699..03118772377 100644 --- a/tests/Core/Command/TwoFactorAuth/EnforceTest.php +++ b/tests/Core/Command/TwoFactorAuth/EnforceTest.php @@ -3,25 +3,8 @@ declare(strict_types=1); /** - * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Command\TwoFactorAuth; @@ -49,7 +32,7 @@ class EnforceTest extends TestCase { $this->command = new CommandTester($command); } - public function testEnforce() { + public function testEnforce(): void { $this->mandatoryTwoFactor->expects($this->once()) ->method('setState') ->with($this->equalTo(new EnforcementState(true))); @@ -63,10 +46,10 @@ class EnforceTest extends TestCase { $this->assertEquals(0, $rc); $display = $this->command->getDisplay(); - $this->assertStringContainsString("Two-factor authentication is enforced for all users", $display); + $this->assertStringContainsString('Two-factor authentication is enforced for all users', $display); } - public function testEnforceForOneGroup() { + public function testEnforceForOneGroup(): void { $this->mandatoryTwoFactor->expects($this->once()) ->method('setState') ->with($this->equalTo(new EnforcementState(true, ['twofactorers']))); @@ -81,10 +64,10 @@ class EnforceTest extends TestCase { $this->assertEquals(0, $rc); $display = $this->command->getDisplay(); - $this->assertStringContainsString("Two-factor authentication is enforced for members of the group(s) twofactorers", $display); + $this->assertStringContainsString('Two-factor authentication is enforced for members of the group(s) twofactorers', $display); } - public function testEnforceForAllExceptOneGroup() { + public function testEnforceForAllExceptOneGroup(): void { $this->mandatoryTwoFactor->expects($this->once()) ->method('setState') ->with($this->equalTo(new EnforcementState(true, [], ['yoloers']))); @@ -99,10 +82,10 @@ class EnforceTest extends TestCase { $this->assertEquals(0, $rc); $display = $this->command->getDisplay(); - $this->assertStringContainsString("Two-factor authentication is enforced for all users, except members of yoloers", $display); + $this->assertStringContainsString('Two-factor authentication is enforced for all users, except members of yoloers', $display); } - public function testDisableEnforced() { + public function testDisableEnforced(): void { $this->mandatoryTwoFactor->expects($this->once()) ->method('setState') ->with(new EnforcementState(false)); @@ -116,10 +99,10 @@ class EnforceTest extends TestCase { $this->assertEquals(0, $rc); $display = $this->command->getDisplay(); - $this->assertStringContainsString("Two-factor authentication is not enforced", $display); + $this->assertStringContainsString('Two-factor authentication is not enforced', $display); } - public function testCurrentStateEnabled() { + public function testCurrentStateEnabled(): void { $this->mandatoryTwoFactor->expects($this->once()) ->method('getState') ->willReturn(new EnforcementState(true)); @@ -128,10 +111,10 @@ class EnforceTest extends TestCase { $this->assertEquals(0, $rc); $display = $this->command->getDisplay(); - $this->assertStringContainsString("Two-factor authentication is enforced for all users", $display); + $this->assertStringContainsString('Two-factor authentication is enforced for all users', $display); } - public function testCurrentStateDisabled() { + public function testCurrentStateDisabled(): void { $this->mandatoryTwoFactor->expects($this->once()) ->method('getState') ->willReturn(new EnforcementState(false)); @@ -140,6 +123,6 @@ class EnforceTest extends TestCase { $this->assertEquals(0, $rc); $display = $this->command->getDisplay(); - $this->assertStringContainsString("Two-factor authentication is not enforced", $display); + $this->assertStringContainsString('Two-factor authentication is not enforced', $display); } } diff --git a/tests/Core/Command/TwoFactorAuth/StateTest.php b/tests/Core/Command/TwoFactorAuth/StateTest.php index bc683c11886..f4ca3c4e031 100644 --- a/tests/Core/Command/TwoFactorAuth/StateTest.php +++ b/tests/Core/Command/TwoFactorAuth/StateTest.php @@ -3,25 +3,8 @@ declare(strict_types=1); /** - * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Core\Command\TwoFactorAuth; @@ -54,16 +37,16 @@ class StateTest extends TestCase { $this->cmd = new CommandTester($cmd); } - public function testWrongUID() { + public function testWrongUID(): void { $this->cmd->execute([ 'uid' => 'nope', ]); $output = $this->cmd->getDisplay(); - $this->assertStringContainsString("Invalid UID", $output); + $this->assertStringContainsString('Invalid UID', $output); } - public function testStateNoProvidersActive() { + public function testStateNoProvidersActive(): void { $user = $this->createMock(IUser::class); $this->userManager->expects($this->once()) ->method('get') @@ -83,10 +66,10 @@ class StateTest extends TestCase { ]); $output = $this->cmd->getDisplay(); - $this->assertStringContainsString("Two-factor authentication is not enabled for user eldora", $output); + $this->assertStringContainsString('Two-factor authentication is not enabled for user eldora', $output); } - public function testStateOneProviderActive() { + public function testStateOneProviderActive(): void { $user = $this->createMock(IUser::class); $this->userManager->expects($this->once()) ->method('get') @@ -106,6 +89,6 @@ class StateTest extends TestCase { ]); $output = $this->cmd->getDisplay(); - $this->assertStringContainsString("Two-factor authentication is enabled for user mohamed", $output); + $this->assertStringContainsString('Two-factor authentication is enabled for user mohamed', $output); } } diff --git a/tests/Core/Command/User/AddTest.php b/tests/Core/Command/User/AddTest.php new file mode 100644 index 00000000000..5a8bc3abea1 --- /dev/null +++ b/tests/Core/Command/User/AddTest.php @@ -0,0 +1,152 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +declare(strict_types=1); + +namespace Core\Command\User; + +use OC\Core\Command\User\Add; +use OCA\Settings\Mailer\NewUserMailHelper; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\IAppConfig; +use OCP\IGroupManager; +use OCP\IUser; +use OCP\IUserManager; +use OCP\Mail\IEMailTemplate; +use OCP\mail\IMailer; +use OCP\Security\ISecureRandom; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Test\TestCase; + +class AddTest extends TestCase { + /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */ + private $userManager; + + /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */ + private $groupManager; + + /** @var IMailer|\PHPUnit\Framework\MockObject\MockObject */ + private $mailer; + + /** @var IAppConfig|\PHPUnit\Framework\MockObject\MockObject */ + private $appConfig; + + /** @var NewUserMailHelper|\PHPUnit\Framework\MockObject\MockObject */ + private $mailHelper; + + /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */ + private $eventDispatcher; + + /** @var ISecureRandom|\PHPUnit\Framework\MockObject\MockObject */ + private $secureRandom; + + /** @var IUser|\PHPUnit\Framework\MockObject\MockObject */ + private $user; + + /** @var InputInterface|\PHPUnit\Framework\MockObject\MockObject */ + private $consoleInput; + + /** @var OutputInterface|\PHPUnit\Framework\MockObject\MockObject */ + private $consoleOutput; + + /** @var Add */ + private $addCommand; + + public function setUp(): void { + parent::setUp(); + + $this->userManager = static::createMock(IUserManager::class); + $this->groupManager = static::createStub(IGroupManager::class); + $this->mailer = static::createMock(IMailer::class); + $this->appConfig = static::createMock(IAppConfig::class); + $this->mailHelper = static::createMock(NewUserMailHelper::class); + $this->eventDispatcher = static::createStub(IEventDispatcher::class); + $this->secureRandom = static::createStub(ISecureRandom::class); + + $this->user = static::createMock(IUser::class); + + $this->consoleInput = static::createMock(InputInterface::class); + $this->consoleOutput = static::createMock(OutputInterface::class); + + $this->addCommand = new Add( + $this->userManager, + $this->groupManager, + $this->mailer, + $this->appConfig, + $this->mailHelper, + $this->eventDispatcher, + $this->secureRandom + ); + } + + #[\PHPUnit\Framework\Attributes\DataProvider('addEmailDataProvider')] + public function testAddEmail( + ?string $email, + bool $isEmailValid, + bool $shouldSendEmail, + ): void { + $this->user->expects($isEmailValid ? static::once() : static::never()) + ->method('setSystemEMailAddress') + ->with(static::equalTo($email)); + + $this->userManager->method('createUser') + ->willReturn($this->user); + + $this->appConfig->method('getValueString') + ->willReturn($shouldSendEmail ? 'yes' : 'no'); + + $this->mailer->method('validateMailAddress') + ->willReturn($isEmailValid); + + $this->mailHelper->method('generateTemplate') + ->willReturn(static::createMock(IEMailTemplate::class)); + + $this->mailHelper->expects($isEmailValid && $shouldSendEmail ? static::once() : static::never()) + ->method('sendMail'); + + $this->consoleInput->method('getOption') + ->willReturnMap([ + ['generate-password', 'true'], + ['email', $email], + ['group', []], + ]); + + $this->invokePrivate($this->addCommand, 'execute', [ + $this->consoleInput, + $this->consoleOutput + ]); + } + + /** + * @return array + */ + public static function addEmailDataProvider(): array { + return [ + 'Valid E-Mail' => [ + 'info@example.com', + true, + true, + ], + 'Invalid E-Mail' => [ + 'info@@example.com', + false, + false, + ], + 'No E-Mail' => [ + '', + false, + false, + ], + 'Valid E-Mail, but no mail should be sent' => [ + 'info@example.com', + true, + false, + ], + ]; + } +} diff --git a/tests/Core/Command/User/AuthTokens/DeleteTest.php b/tests/Core/Command/User/AuthTokens/DeleteTest.php new file mode 100644 index 00000000000..6692473c240 --- /dev/null +++ b/tests/Core/Command/User/AuthTokens/DeleteTest.php @@ -0,0 +1,166 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace Tests\Core\Command\User\AuthTokens; + +use OC\Authentication\Token\IProvider; +use OC\Core\Command\User\AuthTokens\Delete; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Test\TestCase; + +class DeleteTest extends TestCase { + /** @var \PHPUnit\Framework\MockObject\MockObject */ + protected $tokenProvider; + /** @var \PHPUnit\Framework\MockObject\MockObject */ + protected $consoleInput; + /** @var \PHPUnit\Framework\MockObject\MockObject */ + protected $consoleOutput; + + /** @var \Symfony\Component\Console\Command\Command */ + protected $command; + + protected function setUp(): void { + parent::setUp(); + + $tokenProvider = $this->tokenProvider = $this->getMockBuilder(IProvider::class) + ->disableOriginalConstructor() + ->getMock(); + $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); + $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); + + /** @var \OC\Authentication\Token\IProvider $tokenProvider */ + $this->command = new Delete($tokenProvider); + } + + public function testDeleteTokenById(): void { + $this->consoleInput->expects($this->exactly(2)) + ->method('getArgument') + ->willReturnMap([ + ['uid', 'user'], + ['id', '42'] + ]); + + $this->consoleInput->expects($this->once()) + ->method('getOption') + ->with('last-used-before') + ->willReturn(null); + + $this->tokenProvider->expects($this->once()) + ->method('invalidateTokenById') + ->with('user', 42); + + $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); + $this->assertSame(Command::SUCCESS, $result); + } + + public function testDeleteTokenByIdRequiresTokenId(): void { + $this->consoleInput->expects($this->exactly(2)) + ->method('getArgument') + ->willReturnMap([ + ['uid', 'user'], + ['id', null] + ]); + + $this->consoleInput->expects($this->once()) + ->method('getOption') + ->with('last-used-before') + ->willReturn(null); + + $this->expectException(RuntimeException::class); + + $this->tokenProvider->expects($this->never())->method('invalidateTokenById'); + + $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); + $this->assertSame(Command::FAILURE, $result); + } + + public function testDeleteTokensLastUsedBefore(): void { + $this->consoleInput->expects($this->exactly(2)) + ->method('getArgument') + ->willReturnMap([ + ['uid', 'user'], + ['id', null] + ]); + + $this->consoleInput->expects($this->once()) + ->method('getOption') + ->with('last-used-before') + ->willReturn('946684800'); + + $this->tokenProvider->expects($this->once()) + ->method('invalidateLastUsedBefore') + ->with('user', 946684800); + + $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); + $this->assertSame(Command::SUCCESS, $result); + } + + public function testLastUsedBeforeAcceptsIso8601Expanded(): void { + $this->consoleInput->expects($this->exactly(2)) + ->method('getArgument') + ->willReturnMap([ + ['uid', 'user'], + ['id', null] + ]); + + $this->consoleInput->expects($this->once()) + ->method('getOption') + ->with('last-used-before') + ->willReturn('2000-01-01T00:00:00Z'); + + $this->tokenProvider->expects($this->once()) + ->method('invalidateLastUsedBefore') + ->with('user', 946684800); + + $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); + $this->assertSame(Command::SUCCESS, $result); + } + + public function testLastUsedBeforeAcceptsYmd(): void { + $this->consoleInput->expects($this->exactly(2)) + ->method('getArgument') + ->willReturnMap([ + ['uid', 'user'], + ['id', null] + ]); + + $this->consoleInput->expects($this->once()) + ->method('getOption') + ->with('last-used-before') + ->willReturn('2000-01-01'); + + $this->tokenProvider->expects($this->once()) + ->method('invalidateLastUsedBefore') + ->with('user', 946684800); + + $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); + $this->assertSame(Command::SUCCESS, $result); + } + + public function testIdAndLastUsedBeforeAreMutuallyExclusive(): void { + $this->consoleInput->expects($this->exactly(2)) + ->method('getArgument') + ->willReturnMap([ + ['uid', 'user'], + ['id', '42'] + ]); + + $this->consoleInput->expects($this->once()) + ->method('getOption') + ->with('last-used-before') + ->willReturn('946684800'); + + $this->expectException(RuntimeException::class); + + $this->tokenProvider->expects($this->never())->method('invalidateLastUsedBefore'); + + $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); + $this->assertSame(Command::SUCCESS, $result); + } +} diff --git a/tests/Core/Command/User/DeleteTest.php b/tests/Core/Command/User/DeleteTest.php index 6ac0ed0353c..4e06b0f91fc 100644 --- a/tests/Core/Command/User/DeleteTest.php +++ b/tests/Core/Command/User/DeleteTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\User; @@ -48,12 +35,12 @@ class DeleteTest extends TestCase { $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); - /** @var \OCP\IUserManager $userManager */ + /** @var IUserManager $userManager */ $this->command = new Delete($userManager); } - public function validUserLastSeen() { + public static function validUserLastSeen(): array { return [ [true, 'The specified user was deleted'], [false, 'The specified user could not be deleted'], @@ -61,12 +48,12 @@ class DeleteTest extends TestCase { } /** - * @dataProvider validUserLastSeen * * @param bool $deleteSuccess * @param string $expectedString */ - public function testValidUser($deleteSuccess, $expectedString) { + #[\PHPUnit\Framework\Attributes\DataProvider('validUserLastSeen')] + public function testValidUser($deleteSuccess, $expectedString): void { $user = $this->getMockBuilder(IUser::class)->getMock(); $user->expects($this->once()) ->method('delete') @@ -89,7 +76,7 @@ class DeleteTest extends TestCase { self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function testInvalidUser() { + public function testInvalidUser(): void { $this->userManager->expects($this->once()) ->method('get') ->with('user') diff --git a/tests/Core/Command/User/DisableTest.php b/tests/Core/Command/User/DisableTest.php index 0e1d1b72ac4..c1bc10dc6bf 100644 --- a/tests/Core/Command/User/DisableTest.php +++ b/tests/Core/Command/User/DisableTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Command\User; @@ -51,7 +35,7 @@ class DisableTest extends TestCase { $this->command = new Disable($this->userManager); } - public function testValidUser() { + public function testValidUser(): void { $user = $this->createMock(IUser::class); $user->expects($this->once()) ->method('setEnabled') @@ -74,7 +58,7 @@ class DisableTest extends TestCase { self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function testInvalidUser() { + public function testInvalidUser(): void { $this->userManager->expects($this->once()) ->method('get') ->with('user') diff --git a/tests/Core/Command/User/EnableTest.php b/tests/Core/Command/User/EnableTest.php index 6ff82aac673..b2820de14ef 100644 --- a/tests/Core/Command/User/EnableTest.php +++ b/tests/Core/Command/User/EnableTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Command\User; @@ -51,7 +35,7 @@ class EnableTest extends TestCase { $this->command = new Enable($this->userManager); } - public function testValidUser() { + public function testValidUser(): void { $user = $this->createMock(IUser::class); $user->expects($this->once()) ->method('setEnabled') @@ -74,7 +58,7 @@ class EnableTest extends TestCase { self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function testInvalidUser() { + public function testInvalidUser(): void { $this->userManager->expects($this->once()) ->method('get') ->with('user') diff --git a/tests/Core/Command/User/LastSeenTest.php b/tests/Core/Command/User/LastSeenTest.php index f861c2e5f77..64c710eacc5 100644 --- a/tests/Core/Command/User/LastSeenTest.php +++ b/tests/Core/Command/User/LastSeenTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Joas Schilling <nickvergessen@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\User; @@ -48,11 +35,11 @@ class LastSeenTest extends TestCase { $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); - /** @var \OCP\IUserManager $userManager */ + /** @var IUserManager $userManager */ $this->command = new LastSeen($userManager); } - public function validUserLastSeen() { + public static function validUserLastSeen(): array { return [ [0, 'never logged in'], [time(), 'last login'], @@ -60,12 +47,12 @@ class LastSeenTest extends TestCase { } /** - * @dataProvider validUserLastSeen * * @param int $lastSeen * @param string $expectedString */ - public function testValidUser($lastSeen, $expectedString) { + #[\PHPUnit\Framework\Attributes\DataProvider('validUserLastSeen')] + public function testValidUser($lastSeen, $expectedString): void { $user = $this->getMockBuilder(IUser::class)->getMock(); $user->expects($this->once()) ->method('getLastLogin') @@ -88,7 +75,7 @@ class LastSeenTest extends TestCase { self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } - public function testInvalidUser() { + public function testInvalidUser(): void { $this->userManager->expects($this->once()) ->method('get') ->with('user') diff --git a/tests/Core/Command/User/ProfileTest.php b/tests/Core/Command/User/ProfileTest.php new file mode 100644 index 00000000000..ff5568bacfc --- /dev/null +++ b/tests/Core/Command/User/ProfileTest.php @@ -0,0 +1,465 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace Core\Command\User; + +use OC\Core\Command\User\Profile; +use OCP\Accounts\IAccount; +use OCP\Accounts\IAccountManager; +use OCP\Accounts\IAccountProperty; +use OCP\IDBConnection; +use OCP\IUser; +use OCP\IUserManager; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Test\TestCase; + +class ProfileTest extends TestCase { + + protected IAccountManager&MockObject $accountManager; + protected IUserManager&MockObject $userManager; + protected IDBConnection&MockObject $connection; + protected InputInterface&MockObject $consoleInput; + protected OutputInterface&MockObject $consoleOutput; + + protected function setUp(): void { + parent::setUp(); + + $this->accountManager = $this->createMock(IAccountManager::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->connection = $this->createMock(IDBConnection::class); + $this->consoleInput = $this->createMock(InputInterface::class); + $this->consoleOutput = $this->createMock(OutputInterface::class); + } + + public function getCommand(array $methods = []): Profile|MockObject { + if (empty($methods)) { + return new Profile($this->userManager, $this->accountManager); + } else { + return $this->getMockBuilder(Profile::class) + ->setConstructorArgs([ + $this->userManager, + $this->accountManager, + ]) + ->onlyMethods($methods) + ->getMock(); + } + } + + public static function dataCheckInput(): array { + return [ + 'Call with existing user should pass check' => [ + [['uid', 'username']], + [], + [], + true, + null, + ], + 'Call with non-existing user should fail check' => [ + [['uid', 'username']], + [], + [], + false, + 'The user "username" does not exist.', + ], + + 'Call with uid, key and --default value should pass check' => [ + [['uid', 'username'], ['key', 'configkey']], + [], + [['--default-value', false, true]], + true, + null, + ], + 'Call with uid and empty key with default-value option should fail check' => [ + [['uid', 'username'], ['key', '']], + [], + [['--default-value', false, true]], + true, + 'The "default-value" option can only be used when specifying a key.', + ], + + 'Call with uid, key, value should pass check' => [ + [['uid', 'username'], ['key', 'configkey'], ['value', '']], + [], + [], + true, + null, + ], + 'Call with uid, empty key and empty value should fail check' => [ + [['uid', 'username'], ['key', ''], ['value', '']], + [], + [], + true, + 'The value argument can only be used when specifying a key.', + ], + 'Call with uid, key, empty value and default-value option should fail check' => [ + [['uid', 'username'], ['key', 'configkey'], ['value', '']], + [], + [['--default-value', false, true]], + true, + 'The value argument can not be used together with "default-value".', + ], + 'Call with uid, key, empty value and update-only option should pass check' => [ + [['uid', 'username'], ['key', 'configkey'], ['value', '']], + [['update-only', true]], + [], + true, + null, + ], + 'Call with uid, key, null value and update-only option should fail check' => [ + [['uid', 'username'], ['key', 'configkey'], ['value', null]], + [['update-only', true]], + [], + true, + 'The "update-only" option can only be used together with "value".', + ], + + 'Call with uid, key and delete option should pass check' => [ + [['uid', 'username'], ['key', 'configkey']], + [['delete', true]], + [], + true, + null, + ], + 'Call with uid, empty key and delete option should fail check' => [ + [['uid', 'username'], ['key', '']], + [['delete', true]], + [], + true, + 'The "delete" option can only be used when specifying a key.', + ], + 'Call with uid, key, delete option and default-value should fail check' => [ + [['uid', 'username'], ['key', 'configkey']], + [['delete', true]], + [['--default-value', false, true]], + true, + 'The "delete" option can not be used together with "default-value".', + ], + 'Call with uid, key, empty value and delete option should fail check' => [ + [['uid', 'username'], ['key', 'configkey'], ['value', '']], + [['delete', true]], + [], + true, + 'The "delete" option can not be used together with "value".', + ], + 'Call with uid, key, delete and error-if-not-exists should pass check' => [ + [['uid', 'username'], ['key', 'configkey']], + [['delete', true], ['error-if-not-exists', true]], + [], + true, + null, + ], + 'Call with uid, key and error-if-not-exists should fail check' => [ + [['uid', 'username'], ['key', 'configkey']], + [['delete', false], ['error-if-not-exists', true]], + [], + true, + 'The "error-if-not-exists" option can only be used together with "delete".', + ], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataCheckInput')] + public function testCheckInput(array $arguments, array $options, array $parameterOptions, bool $existingUser, ?string $expectedException): void { + $this->consoleInput->expects($this->any()) + ->method('getArgument') + ->willReturnMap($arguments); + $this->consoleInput->expects($this->any()) + ->method('getOption') + ->willReturnMap($options); + $this->consoleInput->expects($this->any()) + ->method('hasParameterOption') + ->willReturnCallback(function (string|array $values, bool $onlyParams = false) use ($parameterOptions): bool { + $arguments = func_get_args(); + foreach ($parameterOptions as $parameterOption) { + // check the arguments of the function, if they are the same, return the mocked value + if (array_diff($arguments, $parameterOption) === []) { + return end($parameterOption); + } + } + + return false; + }); + + $returnedUser = null; + if ($existingUser) { + $mockUser = $this->createMock(IUser::class); + $mockUser->expects($this->once())->method('getUID')->willReturn('user'); + $returnedUser = $mockUser; + } + $this->userManager->expects($this->once()) + ->method('get') + ->willReturn($returnedUser); + + $command = $this->getCommand(); + try { + $this->invokePrivate($command, 'checkInput', [$this->consoleInput]); + $this->assertNull($expectedException); + } catch (\InvalidArgumentException $e) { + $this->assertEquals($expectedException, $e->getMessage()); + } + } + + public function testCheckInputExceptionCatch(): void { + $command = $this->getCommand(['checkInput']); + $command->expects($this->once()) + ->method('checkInput') + ->willThrowException(new \InvalidArgumentException('test')); + + $this->consoleOutput->expects($this->once()) + ->method('writeln') + ->with('<error>test</error>'); + + $this->assertEquals(1, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); + } + + public static function dataExecuteDeleteProfileProperty(): array { + return [ + 'Deleting existing property should succeed' => ['address', 'Berlin', false, null, Command::SUCCESS], + 'Deleting existing property with error-if-not-exists should succeed' => ['address', 'Berlin', true, null, Command::SUCCESS], + 'Deleting non-existing property should succeed' => ['address', '', false, null, Command::SUCCESS], + 'Deleting non-existing property with error-if-not-exists should fail' => ['address', '', true, '<error>The property does not exist for user "username".</error>', Command::FAILURE], + ]; + } + + /** + * Tests the deletion mechanism on profile settings. + */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataExecuteDeleteProfileProperty')] + public function testExecuteDeleteProfileProperty(string $configKey, string $value, bool $errorIfNotExists, ?string $expectedLine, int $expectedReturn): void { + $uid = 'username'; + $appName = 'profile'; + $command = $this->getCommand([ + 'writeArrayInOutputFormat', + 'checkInput', + ]); + + $this->consoleInput->expects($this->any()) + ->method('getArgument') + ->willReturnMap([ + ['uid', $uid], + ['app', $appName], + ['key', $configKey], + ]); + + $mocks = $this->setupProfilePropertiesMock([$configKey => $value]); + + $command->expects($this->once()) + ->method('checkInput') + ->willReturn($mocks['userMock']); + + $this->consoleInput->expects($this->atLeastOnce()) + ->method('hasParameterOption') + ->willReturnMap([ + ['--delete', false, true], + ['--error-if-not-exists', false, $errorIfNotExists], + ]); + + if ($expectedLine === null) { + $this->consoleOutput->expects($this->never()) + ->method('writeln'); + $mocks['profilePropertiesMocks'][0]->expects($this->once()) + ->method('setValue') + ->with(''); + $this->accountManager->expects($this->once()) + ->method('updateAccount') + ->with($mocks['accountMock']); + } else { + $this->consoleOutput->expects($this->once()) + ->method('writeln') + ->with($expectedLine); + $this->accountManager->expects($this->never()) + ->method('updateAccount'); + } + + $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); + } + + public function testExecuteSetProfileProperty(): void { + $command = $this->getCommand([ + 'writeArrayInOutputFormat', + 'checkInput', + ]); + + $uid = 'username'; + $propertyKey = 'address'; + $propertyValue = 'Barcelona'; + + $this->consoleInput->expects($this->atLeast(3)) + ->method('getArgument') + ->willReturnMap([ + ['uid', $uid], + ['key', $propertyKey], + ['value', $propertyValue], + ]); + + $mocks = $this->setupProfilePropertiesMock([$propertyKey => $propertyValue]); + + $command->expects($this->once()) + ->method('checkInput') + ->willReturn($mocks['userMock']); + + $mocks['profilePropertiesMocks'][0]->expects($this->once()) + ->method('setValue') + ->with($propertyValue); + $this->accountManager->expects($this->once()) + ->method('updateAccount') + ->with($mocks['accountMock']); + + $this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); + } + + public static function dataExecuteGet(): array { + return [ + 'Get property with set value should pass' => ['configkey', 'value', null, 'value', Command::SUCCESS], + 'Get property with empty value and default-value option should pass' => ['configkey', '', 'default-value', 'default-value', Command::SUCCESS], + 'Get property with empty value should fail' => ['configkey', '', null, '<error>The property does not exist for user "username".</error>', Command::FAILURE], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataExecuteGet')] + public function testExecuteGet(string $key, string $value, ?string $defaultValue, string $expectedLine, int $expectedReturn): void { + $command = $this->getCommand([ + 'writeArrayInOutputFormat', + 'checkInput', + ]); + + $uid = 'username'; + + $this->consoleInput->expects($this->any()) + ->method('getArgument') + ->willReturnMap([ + ['uid', $uid], + ['key', $key], + ]); + + $mocks = $this->setupProfilePropertiesMock([$key => $value]); + + $command->expects($this->once()) + ->method('checkInput') + ->willReturn($mocks['userMock']); + + if ($value === '') { + if ($defaultValue === null) { + $this->consoleInput->expects($this->atLeastOnce()) + ->method('hasParameterOption') + ->willReturn(false); + } else { + $this->consoleInput->expects($this->atLeastOnce()) + ->method('hasParameterOption') + ->willReturnCallback(fn (string|array $values): bool => $values === '--default-value'); + $this->consoleInput->expects($this->once()) + ->method('getOption') + ->with('default-value') + ->willReturn($defaultValue); + } + } + + $this->consoleOutput->expects($this->once()) + ->method('writeln') + ->with($expectedLine); + + $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); + } + + public function testExecuteList(): void { + $uid = 'username'; + $profileData = [ + 'pronouns' => 'they/them', + 'address' => 'Berlin', + ]; + + $command = $this->getCommand([ + 'writeArrayInOutputFormat', + 'checkInput', + ]); + + $this->consoleInput->expects($this->any()) + ->method('getArgument') + ->willReturnMap([ + ['uid', $uid], + ['key', ''], + ]); + + $mocks = $this->setupProfilePropertiesMock(['address' => $profileData['address'], 'pronouns' => $profileData['pronouns']]); + + $command->expects($this->once()) + ->method('checkInput') + ->willReturn($mocks['userMock']); + + $command->expects($this->once()) + ->method('writeArrayInOutputFormat') + ->with($this->consoleInput, $this->consoleOutput, $profileData); + + + $this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); + } + + /** + * Helper to avoid boilerplate in tests in this file when mocking objects + * of IAccountProperty type. + * + * @param array<string, string> $properties the properties to be set up as key => value + * @return array{ + * userMock: IUser&MockObject, + * accountMock: IAccount&MockObject, + * profilePropertiesMocks: IAccountProperty&MockObject[] + * } + */ + private function setupProfilePropertiesMock(array $properties): array { + $userMock = $this->createMock(IUser::class); + $accountMock = $this->createMock(IAccount::class); + $this->accountManager->expects($this->atLeastOnce()) + ->method('getAccount') + ->with($userMock) + ->willReturn($accountMock); + + /** @var IAccountProperty&MockObject[] $propertiesMocks */ + $propertiesMocks = []; + foreach ($properties as $key => $value) { + $propertiesMocks[] = $this->getAccountPropertyMock($key, $value); + } + + if (count($properties) === 1) { + $accountMock->expects($this->atLeastOnce()) + ->method('getProperty') + ->with(array_keys($properties)[0]) + ->willReturn($propertiesMocks[array_key_first($propertiesMocks)]); + } else { + $accountMock->expects($this->atLeastOnce()) + ->method('getAllProperties') + ->willReturnCallback(function () use ($propertiesMocks) { + foreach ($propertiesMocks as $property) { + yield $property; + } + }); + } + + return [ + 'userMock' => $userMock, + 'accountMock' => $accountMock, + 'profilePropertiesMocks' => $propertiesMocks, + ]; + } + + private function getAccountPropertyMock(string $name, string $value): IAccountProperty&MockObject { + $propertyMock = $this->getMockBuilder(IAccountProperty::class) + ->disableOriginalConstructor() + ->getMock(); + $propertyMock->expects($this->any()) + ->method('getName') + ->willReturn($name); + $propertyMock->expects($this->any()) + ->method('getValue') + ->willReturn($value); + + return $propertyMock; + } +} diff --git a/tests/Core/Command/User/SettingTest.php b/tests/Core/Command/User/SettingTest.php index 964a707bf38..706e5b24742 100644 --- a/tests/Core/Command/User/SettingTest.php +++ b/tests/Core/Command/User/SettingTest.php @@ -1,83 +1,56 @@ <?php + /** - * @author Joas Schilling <coding@schilljs.com> - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Command\User; +use InvalidArgumentException; use OC\Core\Command\User\Setting; use OCP\IConfig; use OCP\IDBConnection; use OCP\IUserManager; +use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; class SettingTest extends TestCase { - /** @var \OCP\IUserManager|\PHPUnit\Framework\MockObject\MockObject */ - protected $userManager; - /** @var \OCP\IConfig|\PHPUnit\Framework\MockObject\MockObject */ - protected $config; - /** @var \OCP\IDBConnection|\PHPUnit\Framework\MockObject\MockObject */ - protected $connection; - /** @var \Symfony\Component\Console\Input\InputInterface|\PHPUnit\Framework\MockObject\MockObject */ - protected $consoleInput; - /** @var \Symfony\Component\Console\Output\OutputInterface|\PHPUnit\Framework\MockObject\MockObject */ - protected $consoleOutput; + protected IUserManager&MockObject $userManager; + protected IConfig&MockObject $config; + protected IDBConnection&MockObject $connection; + protected InputInterface&MockObject $consoleInput; + protected MockObject&OutputInterface $consoleOutput; protected function setUp(): void { parent::setUp(); - $this->userManager = $this->getMockBuilder(IUserManager::class) - ->disableOriginalConstructor() - ->getMock(); - $this->config = $this->getMockBuilder(IConfig::class) - ->disableOriginalConstructor() - ->getMock(); - $this->connection = $this->getMockBuilder(IDBConnection::class) - ->disableOriginalConstructor() - ->getMock(); - $this->consoleInput = $this->getMockBuilder(InputInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->consoleOutput = $this->getMockBuilder(OutputInterface::class) - ->disableOriginalConstructor() - ->getMock(); + $this->userManager = $this->createMock(IUserManager::class); + $this->config = $this->createMock(IConfig::class); + $this->connection = $this->createMock(IDBConnection::class); + $this->consoleInput = $this->createMock(InputInterface::class); + $this->consoleOutput = $this->createMock(OutputInterface::class); } public function getCommand(array $methods = []) { if (empty($methods)) { - return new Setting($this->userManager, $this->config, $this->connection); + return new Setting($this->userManager, $this->config); } else { - $mock = $this->getMockBuilder('OC\Core\Command\User\Setting') + $mock = $this->getMockBuilder(Setting::class) ->setConstructorArgs([ $this->userManager, $this->config, - $this->connection, ]) - ->setMethods($methods) + ->onlyMethods($methods) ->getMock(); return $mock; } } - public function dataCheckInput() { + public static function dataCheckInput(): array { return [ [ [['uid', 'username']], @@ -191,7 +164,6 @@ class SettingTest extends TestCase { } /** - * @dataProvider dataCheckInput * * @param array $arguments * @param array $options @@ -199,7 +171,8 @@ class SettingTest extends TestCase { * @param mixed $user * @param string $expectedException */ - public function testCheckInput($arguments, $options, $parameterOptions, $user, $expectedException) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataCheckInput')] + public function testCheckInput($arguments, $options, $parameterOptions, $user, $expectedException): void { $this->consoleInput->expects($this->any()) ->method('getArgument') ->willReturnMap($arguments); @@ -208,7 +181,16 @@ class SettingTest extends TestCase { ->willReturnMap($options); $this->consoleInput->expects($this->any()) ->method('hasParameterOption') - ->willReturnMap($parameterOptions); + ->willReturnCallback(function (string|array $config, bool $default = false) use ($parameterOptions): bool { + foreach ($parameterOptions as $parameterOption) { + if ($config === $parameterOption[0] + // Check the default value if the maps has 3 entries + && (!isset($parameterOption[2]) || $default === $parameterOption[1])) { + return end($parameterOption); + } + } + return false; + }); if ($user !== false) { $this->userManager->expects($this->once()) @@ -223,16 +205,16 @@ class SettingTest extends TestCase { try { $this->invokePrivate($command, 'checkInput', [$this->consoleInput]); $this->assertFalse($expectedException); - } catch (\InvalidArgumentException $e) { + } catch (InvalidArgumentException $e) { $this->assertEquals($expectedException, $e->getMessage()); } } - public function testCheckInputExceptionCatch() { + public function testCheckInputExceptionCatch(): void { $command = $this->getCommand(['checkInput']); $command->expects($this->once()) ->method('checkInput') - ->willThrowException(new \InvalidArgumentException('test')); + ->willThrowException(new InvalidArgumentException('test')); $this->consoleOutput->expects($this->once()) ->method('writeln') @@ -241,7 +223,7 @@ class SettingTest extends TestCase { $this->assertEquals(1, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); } - public function dataExecuteDelete() { + public static function dataExecuteDelete(): array { return [ ['config', false, null, 0], ['config', true, null, 0], @@ -251,14 +233,14 @@ class SettingTest extends TestCase { } /** - * @dataProvider dataExecuteDelete * * @param string|null $value * @param bool $errorIfNotExists * @param string $expectedLine * @param int $expectedReturn */ - public function testExecuteDelete($value, $errorIfNotExists, $expectedLine, $expectedReturn) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataExecuteDelete')] + public function testExecuteDelete($value, $errorIfNotExists, $expectedLine, $expectedReturn): void { $command = $this->getCommand([ 'writeArrayInOutputFormat', 'checkInput', @@ -305,7 +287,7 @@ class SettingTest extends TestCase { $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); } - public function dataExecuteSet() { + public static function dataExecuteSet(): array { return [ ['config', false, null, 0], ['config', true, null, 0], @@ -315,14 +297,14 @@ class SettingTest extends TestCase { } /** - * @dataProvider dataExecuteSet * * @param string|null $value * @param bool $updateOnly * @param string $expectedLine * @param int $expectedReturn */ - public function testExecuteSet($value, $updateOnly, $expectedLine, $expectedReturn) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataExecuteSet')] + public function testExecuteSet($value, $updateOnly, $expectedLine, $expectedReturn): void { $command = $this->getCommand([ 'writeArrayInOutputFormat', 'checkInput', @@ -373,7 +355,7 @@ class SettingTest extends TestCase { $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); } - public function dataExecuteGet() { + public static function dataExecuteGet(): array { return [ ['config', null, 'config', 0], [null, 'config', 'config', 0], @@ -382,14 +364,14 @@ class SettingTest extends TestCase { } /** - * @dataProvider dataExecuteGet * * @param string|null $value * @param string|null $defaultValue * @param string $expectedLine * @param int $expectedReturn */ - public function testExecuteGet($value, $defaultValue, $expectedLine, $expectedReturn) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataExecuteGet')] + public function testExecuteGet($value, $defaultValue, $expectedLine, $expectedReturn): void { $command = $this->getCommand([ 'writeArrayInOutputFormat', 'checkInput', @@ -416,15 +398,16 @@ class SettingTest extends TestCase { if ($defaultValue === null) { $this->consoleInput->expects($this->atLeastOnce()) ->method('hasParameterOption') - ->willReturnMap([ - ['--default-value', false], - ]); + ->willReturn(false); } else { $this->consoleInput->expects($this->atLeastOnce()) ->method('hasParameterOption') - ->willReturnMap([ - ['--default-value', false, true], - ]); + ->willReturnCallback(function (string|array $config, bool $default = false): bool { + if ($config === '--default-value' && $default === false) { + return true; + } + return false; + }); $this->consoleInput->expects($this->once()) ->method('getOption') ->with('default-value') @@ -439,7 +422,7 @@ class SettingTest extends TestCase { $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); } - public function testExecuteList() { + public function testExecuteList(): void { $command = $this->getCommand([ 'writeArrayInOutputFormat', 'checkInput', diff --git a/tests/Core/Controller/AppPasswordControllerTest.php b/tests/Core/Controller/AppPasswordControllerTest.php index 47220fcf5ab..eb1566eca8b 100644 --- a/tests/Core/Controller/AppPasswordControllerTest.php +++ b/tests/Core/Controller/AppPasswordControllerTest.php @@ -2,25 +2,8 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2018, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Controller; @@ -29,6 +12,7 @@ use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Token\IProvider; use OC\Authentication\Token\IToken; use OC\Core\Controller\AppPasswordController; +use OC\User\Session; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSForbiddenException; use OCP\Authentication\Exceptions\CredentialsUnavailableException; @@ -38,6 +22,8 @@ use OCP\Authentication\LoginCredentials\IStore; use OCP\EventDispatcher\IEventDispatcher; use OCP\IRequest; use OCP\ISession; +use OCP\IUserManager; +use OCP\Security\Bruteforce\IThrottler; use OCP\Security\ISecureRandom; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; @@ -61,6 +47,15 @@ class AppPasswordControllerTest extends TestCase { /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */ private $eventDispatcher; + /** @var Session|MockObject */ + private $userSession; + + /** @var IUserManager|MockObject */ + private $userManager; + + /** @var IThrottler|MockObject */ + private $throttler; + /** @var AppPasswordController */ private $controller; @@ -73,6 +68,9 @@ class AppPasswordControllerTest extends TestCase { $this->credentialStore = $this->createMock(IStore::class); $this->request = $this->createMock(IRequest::class); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); + $this->userSession = $this->createMock(Session::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->throttler = $this->createMock(IThrottler::class); $this->controller = new AppPasswordController( 'core', @@ -81,11 +79,14 @@ class AppPasswordControllerTest extends TestCase { $this->random, $this->tokenProvider, $this->credentialStore, - $this->eventDispatcher + $this->eventDispatcher, + $this->userSession, + $this->userManager, + $this->throttler ); } - public function testGetAppPasswordWithAppPassword() { + public function testGetAppPasswordWithAppPassword(): void { $this->session->method('exists') ->with('app_password') ->willReturn(true); @@ -95,7 +96,7 @@ class AppPasswordControllerTest extends TestCase { $this->controller->getAppPassword(); } - public function testGetAppPasswordNoLoginCreds() { + public function testGetAppPasswordNoLoginCreds(): void { $this->session->method('exists') ->with('app_password') ->willReturn(false); @@ -107,7 +108,7 @@ class AppPasswordControllerTest extends TestCase { $this->controller->getAppPassword(); } - public function testGetAppPassword() { + public function testGetAppPassword(): void { $credentials = $this->createMock(ICredentials::class); $this->session->method('exists') @@ -122,12 +123,12 @@ class AppPasswordControllerTest extends TestCase { $credentials->method('getLoginName') ->willReturn('myLoginName'); $this->request->method('getHeader') - ->with('USER_AGENT') + ->with('user-agent') ->willReturn('myUA'); $this->random->method('generate') ->with( 72, - ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS + ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS )->willReturn('myToken'); $this->tokenProvider->expects($this->once()) @@ -148,7 +149,7 @@ class AppPasswordControllerTest extends TestCase { $this->controller->getAppPassword(); } - public function testGetAppPasswordNoPassword() { + public function testGetAppPasswordNoPassword(): void { $credentials = $this->createMock(ICredentials::class); $this->session->method('exists') @@ -163,12 +164,12 @@ class AppPasswordControllerTest extends TestCase { $credentials->method('getLoginName') ->willReturn('myLoginName'); $this->request->method('getHeader') - ->with('USER_AGENT') + ->with('user-agent') ->willReturn('myUA'); $this->random->method('generate') ->with( 72, - ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS + ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS )->willReturn('myToken'); $this->tokenProvider->expects($this->once()) @@ -189,7 +190,7 @@ class AppPasswordControllerTest extends TestCase { $this->controller->getAppPassword(); } - public function testDeleteAppPasswordNoAppPassword() { + public function testDeleteAppPasswordNoAppPassword(): void { $this->session->method('exists') ->with('app_password') ->willReturn(false); @@ -199,7 +200,7 @@ class AppPasswordControllerTest extends TestCase { $this->controller->deleteAppPassword(); } - public function testDeleteAppPasswordFails() { + public function testDeleteAppPasswordFails(): void { $this->session->method('exists') ->with('app_password') ->willReturn(true); @@ -216,7 +217,7 @@ class AppPasswordControllerTest extends TestCase { $this->controller->deleteAppPassword(); } - public function testDeleteAppPasswordSuccess() { + public function testDeleteAppPasswordSuccess(): void { $this->session->method('exists') ->with('app_password') ->willReturn(true); diff --git a/tests/Core/Controller/AutoCompleteControllerTest.php b/tests/Core/Controller/AutoCompleteControllerTest.php index 6b2f9a4f163..c5574f78fc1 100644 --- a/tests/Core/Controller/AutoCompleteControllerTest.php +++ b/tests/Core/Controller/AutoCompleteControllerTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Controller; @@ -32,13 +16,13 @@ use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class AutoCompleteControllerTest extends TestCase { - /** @var ISearch|MockObject */ + /** @var ISearch|MockObject */ protected $collaboratorSearch; - /** @var IManager|MockObject */ + /** @var IManager|MockObject */ protected $autoCompleteManager; - /** @var IEventDispatcher|MockObject */ + /** @var IEventDispatcher|MockObject */ protected $dispatcher; - /** @var AutoCompleteController */ + /** @var AutoCompleteController */ protected $controller; protected function setUp(): void { @@ -59,7 +43,7 @@ class AutoCompleteControllerTest extends TestCase { ); } - public function searchDataProvider() { + public static function searchDataProvider(): array { return [ [ #0 – regular search // searchResults @@ -170,10 +154,8 @@ class AutoCompleteControllerTest extends TestCase { ]; } - /** - * @dataProvider searchDataProvider - */ - public function testGet(array $searchResults, array $expected, string $searchTerm, ?string $itemType, ?string $itemId, ?string $sorter) { + #[\PHPUnit\Framework\Attributes\DataProvider('searchDataProvider')] + public function testGet(array $searchResults, array $expected, string $searchTerm, ?string $itemType, ?string $itemId, ?string $sorter): void { $this->collaboratorSearch->expects($this->once()) ->method('search') ->willReturn([$searchResults, false]); diff --git a/tests/Core/Controller/AvatarControllerTest.php b/tests/Core/Controller/AvatarControllerTest.php index 256f5665795..a78e2c1bb5c 100644 --- a/tests/Core/Controller/AvatarControllerTest.php +++ b/tests/Core/Controller/AvatarControllerTest.php @@ -1,22 +1,9 @@ <?php + /** - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace OC\Core\Controller; @@ -33,6 +20,7 @@ namespace Tests\Core\Controller; use OC\AppFramework\Utility\TimeFactory; use OC\Core\Controller\AvatarController; +use OC\Core\Controller\GuestAvatarController; use OCP\AppFramework\Http; use OCP\Files\File; use OCP\Files\IRootFolder; @@ -56,13 +44,15 @@ use Psr\Log\LoggerInterface; class AvatarControllerTest extends \Test\TestCase { /** @var AvatarController */ private $avatarController; + /** @var GuestAvatarController */ + private $guestAvatarController; + /** @var IAvatar|\PHPUnit\Framework\MockObject\MockObject */ private $avatarMock; /** @var IUser|\PHPUnit\Framework\MockObject\MockObject */ private $userMock; /** @var ISimpleFile|\PHPUnit\Framework\MockObject\MockObject */ private $avatarFile; - /** @var IAvatarManager|\PHPUnit\Framework\MockObject\MockObject */ private $avatarManager; /** @var ICache|\PHPUnit\Framework\MockObject\MockObject */ @@ -97,6 +87,13 @@ class AvatarControllerTest extends \Test\TestCase { $this->avatarMock = $this->getMockBuilder('OCP\IAvatar')->getMock(); $this->userMock = $this->getMockBuilder(IUser::class)->getMock(); + $this->guestAvatarController = new GuestAvatarController( + 'core', + $this->request, + $this->avatarManager, + $this->logger + ); + $this->avatarController = new AvatarController( 'core', $this->request, @@ -107,7 +104,8 @@ class AvatarControllerTest extends \Test\TestCase { $this->rootFolder, $this->logger, 'userid', - $this->timeFactory + $this->timeFactory, + $this->guestAvatarController, ); // Configure userMock @@ -131,9 +129,9 @@ class AvatarControllerTest extends \Test\TestCase { /** * Fetch an avatar if a user has no avatar */ - public function testGetAvatarNoAvatar() { + public function testGetAvatarNoAvatar(): void { $this->avatarManager->method('getAvatar')->willReturn($this->avatarMock); - $this->avatarMock->method('getFile')->will($this->throwException(new NotFoundException())); + $this->avatarMock->method('getFile')->willThrowException(new NotFoundException()); $response = $this->avatarController->getAvatar('userId', 32); //Comment out until JS is fixed @@ -143,7 +141,7 @@ class AvatarControllerTest extends \Test\TestCase { /** * Fetch the user's avatar */ - public function testGetAvatar() { + public function testGetAvatar(): void { $this->avatarMock->method('getFile')->willReturn($this->avatarFile); $this->avatarManager->method('getAvatar')->with('userId')->willReturn($this->avatarMock); $this->avatarMock->expects($this->once()) @@ -164,7 +162,7 @@ class AvatarControllerTest extends \Test\TestCase { /** * Fetch the user's avatar */ - public function testGetGeneratedAvatar() { + public function testGetGeneratedAvatar(): void { $this->avatarMock->method('getFile')->willReturn($this->avatarFile); $this->avatarManager->method('getAvatar')->with('userId')->willReturn($this->avatarMock); @@ -182,11 +180,11 @@ class AvatarControllerTest extends \Test\TestCase { /** * Fetch the avatar of a non-existing user */ - public function testGetAvatarNoUser() { + public function testGetAvatarNoUser(): void { $this->avatarManager ->method('getAvatar') ->with('userDoesNotExist') - ->will($this->throwException(new \Exception('user does not exist'))); + ->willThrowException(new \Exception('user does not exist')); $response = $this->avatarController->getAvatar('userDoesNotExist', 32); @@ -279,7 +277,7 @@ class AvatarControllerTest extends \Test\TestCase { /** * Remove an avatar */ - public function testDeleteAvatar() { + public function testDeleteAvatar(): void { $this->avatarManager->method('getAvatar')->willReturn($this->avatarMock); $response = $this->avatarController->deleteAvatar(); @@ -289,13 +287,13 @@ class AvatarControllerTest extends \Test\TestCase { /** * Test what happens if the removing of the avatar fails */ - public function testDeleteAvatarException() { - $this->avatarMock->method('remove')->will($this->throwException(new \Exception("foo"))); + public function testDeleteAvatarException(): void { + $this->avatarMock->method('remove')->willThrowException(new \Exception('foo')); $this->avatarManager->method('getAvatar')->willReturn($this->avatarMock); $this->logger->expects($this->once()) ->method('error') - ->with('foo', ['exception' => new \Exception("foo"), 'app' => 'core']); + ->with('foo', ['exception' => new \Exception('foo'), 'app' => 'core']); $expectedResponse = new Http\JSONResponse(['data' => ['message' => 'An error occurred. Please contact your admin.']], Http::STATUS_BAD_REQUEST); $this->assertEquals($expectedResponse, $this->avatarController->deleteAvatar()); } @@ -303,7 +301,7 @@ class AvatarControllerTest extends \Test\TestCase { /** * Trying to get a tmp avatar when it is not available. 404 */ - public function testTmpAvatarNoTmp() { + public function testTmpAvatarNoTmp(): void { $response = $this->avatarController->getTmpAvatar(); $this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus()); } @@ -311,8 +309,8 @@ class AvatarControllerTest extends \Test\TestCase { /** * Fetch tmp avatar */ - public function testTmpAvatarValid() { - $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT.'/tests/data/testimage.jpg')); + public function testTmpAvatarValid(): void { + $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT . '/tests/data/testimage.jpg')); $response = $this->avatarController->getTmpAvatar(); $this->assertEquals(Http::STATUS_OK, $response->getStatus()); @@ -322,7 +320,7 @@ class AvatarControllerTest extends \Test\TestCase { /** * When trying to post a new avatar a path or image should be posted. */ - public function testPostAvatarNoPathOrImage() { + public function testPostAvatarNoPathOrImage(): void { $response = $this->avatarController->postAvatar(null); $this->assertEquals(Http::STATUS_BAD_REQUEST, $response->getStatus()); @@ -331,17 +329,17 @@ class AvatarControllerTest extends \Test\TestCase { /** * Test a correct post of an avatar using POST */ - public function testPostAvatarFile() { + public function testPostAvatarFile(): void { //Create temp file - $fileName = tempnam('', "avatarTest"); - $copyRes = copy(\OC::$SERVERROOT.'/tests/data/testimage.jpg', $fileName); + $fileName = tempnam('', 'avatarTest'); + $copyRes = copy(\OC::$SERVERROOT . '/tests/data/testimage.jpg', $fileName); $this->assertTrue($copyRes); //Create file in cache - $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT.'/tests/data/testimage.jpg')); + $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT . '/tests/data/testimage.jpg')); //Create request return - $reqRet = ['error' => [0], 'tmp_name' => [$fileName], 'size' => [filesize(\OC::$SERVERROOT.'/tests/data/testimage.jpg')]]; + $reqRet = ['error' => [0], 'tmp_name' => [$fileName], 'size' => [filesize(\OC::$SERVERROOT . '/tests/data/testimage.jpg')]]; $this->request->method('getUploadedFile')->willReturn($reqRet); $response = $this->avatarController->postAvatar(null); @@ -356,7 +354,7 @@ class AvatarControllerTest extends \Test\TestCase { /** * Test invalid post os an avatar using POST */ - public function testPostAvatarInvalidFile() { + public function testPostAvatarInvalidFile(): void { //Create request return $reqRet = ['error' => [1], 'tmp_name' => ['foo']]; $this->request->method('getUploadedFile')->willReturn($reqRet); @@ -369,17 +367,17 @@ class AvatarControllerTest extends \Test\TestCase { /** * Check what happens when we upload a GIF */ - public function testPostAvatarFileGif() { + public function testPostAvatarFileGif(): void { //Create temp file - $fileName = tempnam('', "avatarTest"); - $copyRes = copy(\OC::$SERVERROOT.'/tests/data/testimage.gif', $fileName); + $fileName = tempnam('', 'avatarTest'); + $copyRes = copy(\OC::$SERVERROOT . '/tests/data/testimage.gif', $fileName); $this->assertTrue($copyRes); //Create file in cache - $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT.'/tests/data/testimage.gif')); + $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT . '/tests/data/testimage.gif')); //Create request return - $reqRet = ['error' => [0], 'tmp_name' => [$fileName], 'size' => [filesize(\OC::$SERVERROOT.'/tests/data/testimage.gif')]]; + $reqRet = ['error' => [0], 'tmp_name' => [$fileName], 'size' => [filesize(\OC::$SERVERROOT . '/tests/data/testimage.gif')]]; $this->request->method('getUploadedFile')->willReturn($reqRet); $response = $this->avatarController->postAvatar(null); @@ -393,13 +391,13 @@ class AvatarControllerTest extends \Test\TestCase { /** * Test posting avatar from existing file */ - public function testPostAvatarFromFile() { + public function testPostAvatarFromFile(): void { //Mock node API call $file = $this->getMockBuilder('OCP\Files\File') ->disableOriginalConstructor()->getMock(); $file->expects($this->once()) ->method('getContent') - ->willReturn(file_get_contents(\OC::$SERVERROOT.'/tests/data/testimage.jpg')); + ->willReturn(file_get_contents(\OC::$SERVERROOT . '/tests/data/testimage.jpg')); $file->expects($this->once()) ->method('getMimeType') ->willReturn('image/jpeg'); @@ -417,7 +415,7 @@ class AvatarControllerTest extends \Test\TestCase { /** * Test posting avatar from existing folder */ - public function testPostAvatarFromNoFile() { + public function testPostAvatarFromNoFile(): void { $file = $this->getMockBuilder('OCP\Files\Node')->getMock(); $userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock(); $this->rootFolder->method('getUserFolder')->with('userid')->willReturn($userFolder); @@ -433,7 +431,7 @@ class AvatarControllerTest extends \Test\TestCase { $this->assertEquals(['data' => ['message' => 'Please select a file.']], $response->getData()); } - public function testPostAvatarInvalidType() { + public function testPostAvatarInvalidType(): void { $file = $this->getMockBuilder('OCP\Files\File') ->disableOriginalConstructor()->getMock(); $file->expects($this->never()) @@ -449,7 +447,7 @@ class AvatarControllerTest extends \Test\TestCase { $this->assertEquals($expectedResponse, $this->avatarController->postAvatar('avatar.jpg')); } - public function testPostAvatarNotPermittedException() { + public function testPostAvatarNotPermittedException(): void { $file = $this->getMockBuilder('OCP\Files\File') ->disableOriginalConstructor()->getMock(); $file->expects($this->once()) @@ -469,15 +467,15 @@ class AvatarControllerTest extends \Test\TestCase { /** * Test what happens if the upload of the avatar fails */ - public function testPostAvatarException() { + public function testPostAvatarException(): void { $this->cache->expects($this->once()) ->method('set') - ->will($this->throwException(new \Exception("foo"))); + ->willThrowException(new \Exception('foo')); $file = $this->getMockBuilder('OCP\Files\File') ->disableOriginalConstructor()->getMock(); $file->expects($this->once()) ->method('getContent') - ->willReturn(file_get_contents(\OC::$SERVERROOT.'/tests/data/testimage.jpg')); + ->willReturn(file_get_contents(\OC::$SERVERROOT . '/tests/data/testimage.jpg')); $file->expects($this->once()) ->method('getMimeType') ->willReturn('image/jpeg'); @@ -487,7 +485,7 @@ class AvatarControllerTest extends \Test\TestCase { $this->logger->expects($this->once()) ->method('error') - ->with('foo', ['exception' => new \Exception("foo"), 'app' => 'core']); + ->with('foo', ['exception' => new \Exception('foo'), 'app' => 'core']); $expectedResponse = new Http\JSONResponse(['data' => ['message' => 'An error occurred. Please contact your admin.']], Http::STATUS_OK); $this->assertEquals($expectedResponse, $this->avatarController->postAvatar('avatar.jpg')); } @@ -496,7 +494,7 @@ class AvatarControllerTest extends \Test\TestCase { /** * Test invalid crop argument */ - public function testPostCroppedAvatarInvalidCrop() { + public function testPostCroppedAvatarInvalidCrop(): void { $response = $this->avatarController->postCroppedAvatar([]); $this->assertEquals(Http::STATUS_BAD_REQUEST, $response->getStatus()); @@ -505,7 +503,7 @@ class AvatarControllerTest extends \Test\TestCase { /** * Test no tmp avatar to crop */ - public function testPostCroppedAvatarNoTmpAvatar() { + public function testPostCroppedAvatarNoTmpAvatar(): void { $response = $this->avatarController->postCroppedAvatar(['x' => 0, 'y' => 0, 'w' => 10, 'h' => 10]); $this->assertEquals(Http::STATUS_BAD_REQUEST, $response->getStatus()); @@ -514,10 +512,10 @@ class AvatarControllerTest extends \Test\TestCase { /** * Test with non square crop */ - public function testPostCroppedAvatarNoSquareCrop() { - $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT.'/tests/data/testimage.jpg')); + public function testPostCroppedAvatarNoSquareCrop(): void { + $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT . '/tests/data/testimage.jpg')); - $this->avatarMock->method('set')->will($this->throwException(new \OC\NotSquareException)); + $this->avatarMock->method('set')->willThrowException(new \OC\NotSquareException); $this->avatarManager->method('getAvatar')->willReturn($this->avatarMock); $response = $this->avatarController->postCroppedAvatar(['x' => 0, 'y' => 0, 'w' => 10, 'h' => 11]); @@ -527,8 +525,8 @@ class AvatarControllerTest extends \Test\TestCase { /** * Check for proper reply on proper crop argument */ - public function testPostCroppedAvatarValidCrop() { - $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT.'/tests/data/testimage.jpg')); + public function testPostCroppedAvatarValidCrop(): void { + $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT . '/tests/data/testimage.jpg')); $this->avatarManager->method('getAvatar')->willReturn($this->avatarMock); $response = $this->avatarController->postCroppedAvatar(['x' => 0, 'y' => 0, 'w' => 10, 'h' => 10]); @@ -539,15 +537,15 @@ class AvatarControllerTest extends \Test\TestCase { /** * Test what happens if the cropping of the avatar fails */ - public function testPostCroppedAvatarException() { - $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT.'/tests/data/testimage.jpg')); + public function testPostCroppedAvatarException(): void { + $this->cache->method('get')->willReturn(file_get_contents(\OC::$SERVERROOT . '/tests/data/testimage.jpg')); - $this->avatarMock->method('set')->will($this->throwException(new \Exception('foo'))); + $this->avatarMock->method('set')->willThrowException(new \Exception('foo')); $this->avatarManager->method('getAvatar')->willReturn($this->avatarMock); $this->logger->expects($this->once()) ->method('error') - ->with('foo', ['exception' => new \Exception("foo"), 'app' => 'core']); + ->with('foo', ['exception' => new \Exception('foo'), 'app' => 'core']); $expectedResponse = new Http\JSONResponse(['data' => ['message' => 'An error occurred. Please contact your admin.']], Http::STATUS_BAD_REQUEST); $this->assertEquals($expectedResponse, $this->avatarController->postCroppedAvatar(['x' => 0, 'y' => 0, 'w' => 10, 'h' => 11])); } @@ -556,8 +554,8 @@ class AvatarControllerTest extends \Test\TestCase { /** * Check for proper reply on proper crop argument */ - public function testFileTooBig() { - $fileName = \OC::$SERVERROOT.'/tests/data/testimage.jpg'; + public function testFileTooBig(): void { + $fileName = \OC::$SERVERROOT . '/tests/data/testimage.jpg'; //Create request return $reqRet = ['error' => [0], 'tmp_name' => [$fileName], 'size' => [21 * 1024 * 1024]]; $this->request->method('getUploadedFile')->willReturn($reqRet); diff --git a/tests/Core/Controller/CSRFTokenControllerTest.php b/tests/Core/Controller/CSRFTokenControllerTest.php index ba01675e978..a401788be8d 100644 --- a/tests/Core/Controller/CSRFTokenControllerTest.php +++ b/tests/Core/Controller/CSRFTokenControllerTest.php @@ -1,25 +1,8 @@ <?php /** - * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Controller; diff --git a/tests/Core/Controller/ChangePasswordControllerTest.php b/tests/Core/Controller/ChangePasswordControllerTest.php index 2d7292f6801..aae36fb52b8 100644 --- a/tests/Core/Controller/ChangePasswordControllerTest.php +++ b/tests/Core/Controller/ChangePasswordControllerTest.php @@ -1,23 +1,8 @@ <?php + /** - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Controller; @@ -76,7 +61,7 @@ class ChangePasswordControllerTest extends \Test\TestCase { ); } - public function testChangePersonalPasswordWrongPassword() { + public function testChangePersonalPasswordWrongPassword(): void { $this->userSession->expects($this->once()) ->method('getLoginName') ->willReturn($this->loginName); @@ -98,7 +83,7 @@ class ChangePasswordControllerTest extends \Test\TestCase { $this->assertEquals($expects, $actual); } - public function testChangePersonalPasswordCommonPassword() { + public function testChangePersonalPasswordCommonPassword(): void { $this->userSession->expects($this->once()) ->method('getLoginName') ->willReturn($this->loginName); @@ -112,7 +97,7 @@ class ChangePasswordControllerTest extends \Test\TestCase { $user->expects($this->once()) ->method('setPassword') ->with('new') - ->will($this->throwException(new HintException('Common password'))); + ->willThrowException(new HintException('Common password')); $expects = new JSONResponse([ 'status' => 'error', @@ -125,7 +110,7 @@ class ChangePasswordControllerTest extends \Test\TestCase { $this->assertEquals($expects, $actual); } - public function testChangePersonalPasswordNoNewPassword() { + public function testChangePersonalPasswordNoNewPassword(): void { $this->userSession->expects($this->once()) ->method('getLoginName') ->willReturn($this->loginName); @@ -148,7 +133,7 @@ class ChangePasswordControllerTest extends \Test\TestCase { $this->assertEquals($expects, $res->getData()); } - public function testChangePersonalPasswordCantSetPassword() { + public function testChangePersonalPasswordCantSetPassword(): void { $this->userSession->expects($this->once()) ->method('getLoginName') ->willReturn($this->loginName); @@ -175,7 +160,7 @@ class ChangePasswordControllerTest extends \Test\TestCase { $this->assertEquals($expects, $actual); } - public function testChangePersonalPassword() { + public function testChangePersonalPassword(): void { $this->userSession->expects($this->once()) ->method('getLoginName') ->willReturn($this->loginName); diff --git a/tests/Core/Controller/ClientFlowLoginControllerTest.php b/tests/Core/Controller/ClientFlowLoginControllerTest.php index dfd3e629dcd..b182bb1bb39 100644 --- a/tests/Core/Controller/ClientFlowLoginControllerTest.php +++ b/tests/Core/Controller/ClientFlowLoginControllerTest.php @@ -1,22 +1,10 @@ <?php + +declare(strict_types=1); + /** - * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Controller; @@ -30,9 +18,14 @@ use OCA\OAuth2\Db\AccessTokenMapper; use OCA\OAuth2\Db\Client; use OCA\OAuth2\Db\ClientMapper; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\ContentSecurityPolicy; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\StandaloneTemplateResponse; +use OCP\AppFramework\Utility\ITimeFactory; use OCP\Defaults; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; use OCP\ISession; @@ -42,37 +35,26 @@ use OCP\IUserSession; use OCP\Security\ICrypto; use OCP\Security\ISecureRandom; use OCP\Session\Exceptions\SessionNotAvailableException; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class ClientFlowLoginControllerTest extends TestCase { - /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */ - private $request; - /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */ - private $userSession; - /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */ - private $l10n; - /** @var Defaults|\PHPUnit\Framework\MockObject\MockObject */ - private $defaults; - /** @var ISession|\PHPUnit\Framework\MockObject\MockObject */ - private $session; - /** @var IProvider|\PHPUnit\Framework\MockObject\MockObject */ - private $tokenProvider; - /** @var ISecureRandom|\PHPUnit\Framework\MockObject\MockObject */ - private $random; - /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */ - private $urlGenerator; - /** @var ClientMapper|\PHPUnit\Framework\MockObject\MockObject */ - private $clientMapper; - /** @var AccessTokenMapper|\PHPUnit\Framework\MockObject\MockObject */ - private $accessTokenMapper; - /** @var ICrypto|\PHPUnit\Framework\MockObject\MockObject */ - private $crypto; - /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */ - private $eventDispatcher; - - - /** @var ClientFlowLoginController */ - private $clientFlowLoginController; + private IRequest&MockObject $request; + private IUserSession&MockObject $userSession; + private IL10N&MockObject $l10n; + private Defaults&MockObject $defaults; + private ISession&MockObject $session; + private IProvider&MockObject $tokenProvider; + private ISecureRandom&MockObject $random; + private IURLGenerator&MockObject $urlGenerator; + private ClientMapper&MockObject $clientMapper; + private AccessTokenMapper&MockObject $accessTokenMapper; + private ICrypto&MockObject $crypto; + private IEventDispatcher&MockObject $eventDispatcher; + private ITimeFactory&MockObject $timeFactory; + private IConfig&MockObject $config; + + private ClientFlowLoginController $clientFlowLoginController; protected function setUp(): void { parent::setUp(); @@ -95,6 +77,8 @@ class ClientFlowLoginControllerTest extends TestCase { $this->accessTokenMapper = $this->createMock(AccessTokenMapper::class); $this->crypto = $this->createMock(ICrypto::class); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); + $this->timeFactory = $this->createMock(ITimeFactory::class); + $this->config = $this->createMock(IConfig::class); $this->clientFlowLoginController = new ClientFlowLoginController( 'core', @@ -109,17 +93,19 @@ class ClientFlowLoginControllerTest extends TestCase { $this->clientMapper, $this->accessTokenMapper, $this->crypto, - $this->eventDispatcher + $this->eventDispatcher, + $this->timeFactory, + $this->config, ); } - public function testShowAuthPickerPageNoClientOrOauthRequest() { + public function testShowAuthPickerPageNoClientOrOauthRequest(): void { $expected = new StandaloneTemplateResponse( 'core', 'error', [ - 'errors' => - [ + 'errors' + => [ [ 'error' => 'Access Forbidden', 'hint' => 'Invalid request', @@ -132,15 +118,11 @@ class ClientFlowLoginControllerTest extends TestCase { $this->assertEquals($expected, $this->clientFlowLoginController->showAuthPickerPage()); } - public function testShowAuthPickerPageWithOcsHeader() { + public function testShowAuthPickerPageWithOcsHeader(): void { $this->request ->method('getHeader') - ->withConsecutive( - ['USER_AGENT'], - ['OCS-APIREQUEST'] - ) ->willReturnMap([ - ['USER_AGENT', 'Mac OS X Sync Client'], + ['user-agent', 'Mac OS X Sync Client'], ['OCS-APIREQUEST', 'true'], ]); $this->random @@ -148,7 +130,7 @@ class ClientFlowLoginControllerTest extends TestCase { ->method('generate') ->with( 64, - ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_DIGITS + ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS ) ->willReturn('StateToken'); $this->session @@ -184,25 +166,22 @@ class ClientFlowLoginControllerTest extends TestCase { 'serverHost' => 'https://example.com', 'oauthState' => 'OauthStateToken', 'user' => '', - 'direct' => 0 + 'direct' => 0, + 'providedRedirectUri' => '', ], 'guest' ); - $csp = new Http\ContentSecurityPolicy(); + $csp = new ContentSecurityPolicy(); $csp->addAllowedFormActionDomain('nc://*'); $expected->setContentSecurityPolicy($csp); $this->assertEquals($expected, $this->clientFlowLoginController->showAuthPickerPage()); } - public function testShowAuthPickerPageWithOauth() { + public function testShowAuthPickerPageWithOauth(): void { $this->request ->method('getHeader') - ->withConsecutive( - ['USER_AGENT'], - ['OCS-APIREQUEST'] - ) ->willReturnMap([ - ['USER_AGENT', 'Mac OS X Sync Client'], + ['user-agent', 'Mac OS X Sync Client'], ['OCS-APIREQUEST', 'false'], ]); $client = new Client(); @@ -218,7 +197,7 @@ class ClientFlowLoginControllerTest extends TestCase { ->method('generate') ->with( 64, - ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_DIGITS + ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS ) ->willReturn('StateToken'); $this->session @@ -254,17 +233,18 @@ class ClientFlowLoginControllerTest extends TestCase { 'serverHost' => 'https://example.com', 'oauthState' => 'OauthStateToken', 'user' => '', - 'direct' => 0 + 'direct' => 0, + 'providedRedirectUri' => '', ], 'guest' ); - $csp = new Http\ContentSecurityPolicy(); + $csp = new ContentSecurityPolicy(); $csp->addAllowedFormActionDomain('https://example.com/redirect.php'); $expected->setContentSecurityPolicy($csp); $this->assertEquals($expected, $this->clientFlowLoginController->showAuthPickerPage('MyClientIdentifier')); } - public function testGenerateAppPasswordWithInvalidToken() { + public function testGenerateAppPasswordWithInvalidToken(): void { $this->session ->expects($this->once()) ->method('get') @@ -287,7 +267,7 @@ class ClientFlowLoginControllerTest extends TestCase { $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken')); } - public function testGenerateAppPasswordWithSessionNotAvailableException() { + public function testGenerateAppPasswordWithSessionNotAvailableException(): void { $this->session ->expects($this->once()) ->method('get') @@ -302,12 +282,12 @@ class ClientFlowLoginControllerTest extends TestCase { ->method('getId') ->willThrowException(new SessionNotAvailableException()); - $expected = new Http\Response(); + $expected = new Response(); $expected->setStatus(Http::STATUS_FORBIDDEN); $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken')); } - public function testGenerateAppPasswordWithInvalidTokenException() { + public function testGenerateAppPasswordWithInvalidTokenException(): void { $this->session ->expects($this->once()) ->method('get') @@ -327,12 +307,12 @@ class ClientFlowLoginControllerTest extends TestCase { ->with('SessionId') ->willThrowException(new InvalidTokenException()); - $expected = new Http\Response(); + $expected = new Response(); $expected->setStatus(Http::STATUS_FORBIDDEN); $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken')); } - public function testGeneratePasswordWithPassword() { + public function testGeneratePasswordWithPassword(): void { $this->session ->expects($this->once()) ->method('get') @@ -403,7 +383,7 @@ class ClientFlowLoginControllerTest extends TestCase { $this->eventDispatcher->expects($this->once()) ->method('dispatchTyped'); - $expected = new Http\RedirectResponse('nc://login/server:http://example.com&user:MyLoginName&password:MyGeneratedToken'); + $expected = new RedirectResponse('nc://login/server:http://example.com&user:MyLoginName&password:MyGeneratedToken'); $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken')); } @@ -416,23 +396,23 @@ class ClientFlowLoginControllerTest extends TestCase { * ["https://example.com/redirect.php?hello=world", "https://example.com/redirect.php?hello=world&state=MyOauthState&code=MyAccessCode"] * */ - public function testGeneratePasswordWithPasswordForOauthClient($redirectUri, $redirectUrl) { + public function testGeneratePasswordWithPasswordForOauthClient($redirectUri, $redirectUrl): void { $this->session ->method('get') - ->withConsecutive( - ['client.flow.state.token'], - ['oauth.state'] - ) ->willReturnMap([ ['client.flow.state.token', 'MyStateToken'], ['oauth.state', 'MyOauthState'], ]); + $calls = [ + 'client.flow.state.token', + 'oauth.state', + ]; $this->session ->method('remove') - ->withConsecutive( - ['client.flow.state.token'], - ['oauth.state'] - ); + ->willReturnCallback(function ($key) use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, $key); + }); $this->session ->expects($this->once()) ->method('getId') @@ -454,13 +434,9 @@ class ClientFlowLoginControllerTest extends TestCase { ->willReturn('MyPassword'); $this->random ->method('generate') - ->withConsecutive( - [72], - [128] - ) ->willReturnMap([ - [72, ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS, 'MyGeneratedToken'], - [128, ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS, 'MyAccessCode'], + [72, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS, 'MyGeneratedToken'], + [128, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS, 'MyAccessCode'], ]); $user = $this->createMock(IUser::class); $user @@ -497,11 +473,11 @@ class ClientFlowLoginControllerTest extends TestCase { $this->eventDispatcher->expects($this->once()) ->method('dispatchTyped'); - $expected = new Http\RedirectResponse($redirectUrl); + $expected = new RedirectResponse($redirectUrl); $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken', 'MyClientIdentifier')); } - public function testGeneratePasswordWithoutPassword() { + public function testGeneratePasswordWithoutPassword(): void { $this->session ->expects($this->once()) ->method('get') @@ -572,17 +548,17 @@ class ClientFlowLoginControllerTest extends TestCase { $this->eventDispatcher->expects($this->once()) ->method('dispatchTyped'); - $expected = new Http\RedirectResponse('nc://login/server:http://example.com&user:MyLoginName&password:MyGeneratedToken'); + $expected = new RedirectResponse('nc://login/server:http://example.com&user:MyLoginName&password:MyGeneratedToken'); $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken')); } - public function dataGeneratePasswordWithHttpsProxy() { + public static function dataGeneratePasswordWithHttpsProxy(): array { return [ [ [ ['X-Forwarded-Proto', 'http'], ['X-Forwarded-Ssl', 'off'], - ['USER_AGENT', ''], + ['user-agent', ''], ], 'http', 'http', @@ -591,7 +567,7 @@ class ClientFlowLoginControllerTest extends TestCase { [ ['X-Forwarded-Proto', 'http'], ['X-Forwarded-Ssl', 'off'], - ['USER_AGENT', ''], + ['user-agent', ''], ], 'https', 'https', @@ -600,7 +576,7 @@ class ClientFlowLoginControllerTest extends TestCase { [ ['X-Forwarded-Proto', 'https'], ['X-Forwarded-Ssl', 'off'], - ['USER_AGENT', ''], + ['user-agent', ''], ], 'http', 'https', @@ -609,7 +585,7 @@ class ClientFlowLoginControllerTest extends TestCase { [ ['X-Forwarded-Proto', 'https'], ['X-Forwarded-Ssl', 'on'], - ['USER_AGENT', ''], + ['user-agent', ''], ], 'http', 'https', @@ -618,7 +594,7 @@ class ClientFlowLoginControllerTest extends TestCase { [ ['X-Forwarded-Proto', 'http'], ['X-Forwarded-Ssl', 'on'], - ['USER_AGENT', ''], + ['user-agent', ''], ], 'http', 'https', @@ -627,12 +603,12 @@ class ClientFlowLoginControllerTest extends TestCase { } /** - * @dataProvider dataGeneratePasswordWithHttpsProxy * @param array $headers * @param string $protocol * @param string $expected */ - public function testGeneratePasswordWithHttpsProxy(array $headers, $protocol, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGeneratePasswordWithHttpsProxy')] + public function testGeneratePasswordWithHttpsProxy(array $headers, $protocol, $expected): void { $this->session ->expects($this->once()) ->method('get') @@ -703,7 +679,7 @@ class ClientFlowLoginControllerTest extends TestCase { $this->eventDispatcher->expects($this->once()) ->method('dispatchTyped'); - $expected = new Http\RedirectResponse('nc://login/server:' . $expected . '://example.com&user:MyLoginName&password:MyGeneratedToken'); + $expected = new RedirectResponse('nc://login/server:' . $expected . '://example.com&user:MyLoginName&password:MyGeneratedToken'); $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken')); } } diff --git a/tests/Core/Controller/ClientFlowLoginV2ControllerTest.php b/tests/Core/Controller/ClientFlowLoginV2ControllerTest.php index a1f50e328dd..d130eb75c1a 100644 --- a/tests/Core/Controller/ClientFlowLoginV2ControllerTest.php +++ b/tests/Core/Controller/ClientFlowLoginV2ControllerTest.php @@ -2,25 +2,8 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Controller; @@ -28,9 +11,12 @@ namespace Test\Core\Controller; use OC\Core\Controller\ClientFlowLoginV2Controller; use OC\Core\Data\LoginFlowV2Credentials; use OC\Core\Db\LoginFlowV2; +use OC\Core\Exception\LoginFlowV2ClientForbiddenException; use OC\Core\Exception\LoginFlowV2NotFoundException; use OC\Core\Service\LoginFlowV2Service; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\AppFramework\Http\StandaloneTemplateResponse; use OCP\Defaults; use OCP\IL10N; use OCP\IRequest; @@ -73,6 +59,12 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $this->random = $this->createMock(ISecureRandom::class); $this->defaults = $this->createMock(Defaults::class); $this->l = $this->createMock(IL10N::class); + $this->l + ->expects($this->any()) + ->method('t') + ->willReturnCallback(function ($text, $parameters = []) { + return vsprintf($text, $parameters); + }); $this->controller = new ClientFlowLoginV2Controller( 'core', $this->request, @@ -87,7 +79,7 @@ class ClientFlowLoginV2ControllerTest extends TestCase { ); } - public function testPollInvalid() { + public function testPollInvalid(): void { $this->loginFlowV2Service->method('poll') ->with('token') ->willThrowException(new LoginFlowV2NotFoundException()); @@ -98,7 +90,7 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $this->assertSame(Http::STATUS_NOT_FOUND, $result->getStatus()); } - public function testPollValid() { + public function testPollValid(): void { $creds = new LoginFlowV2Credentials('server', 'login', 'pass'); $this->loginFlowV2Service->method('poll') ->with('token') @@ -106,11 +98,11 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $result = $this->controller->poll('token'); - $this->assertSame($creds, $result->getData()); + $this->assertSame($creds->jsonSerialize(), $result->getData()); $this->assertSame(Http::STATUS_OK, $result->getStatus()); } - public function testLandingInvalid() { + public function testLandingInvalid(): void { $this->session->expects($this->never()) ->method($this->anything()); @@ -121,10 +113,10 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $result = $this->controller->landing('token'); $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); - $this->assertInstanceOf(Http\StandaloneTemplateResponse::class, $result); + $this->assertInstanceOf(StandaloneTemplateResponse::class, $result); } - public function testLandingValid() { + public function testLandingValid(): void { $this->session->expects($this->once()) ->method('set') ->with('client.flow.v2.login.token', 'token'); @@ -139,12 +131,12 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $result = $this->controller->landing('token'); - $this->assertInstanceOf(Http\RedirectResponse::class, $result); + $this->assertInstanceOf(RedirectResponse::class, $result); $this->assertSame(Http::STATUS_SEE_OTHER, $result->getStatus()); $this->assertSame('https://server/path', $result->getRedirectURL()); } - public function testShowAuthPickerNoLoginToken() { + public function testShowAuthPickerNoLoginToken(): void { $this->session->method('get') ->willReturn(null); @@ -153,7 +145,7 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); } - public function testShowAuthPickerInvalidLoginToken() { + public function testShowAuthPickerInvalidLoginToken(): void { $this->session->method('get') ->with('client.flow.v2.login.token') ->willReturn('loginToken'); @@ -167,7 +159,23 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); } - public function testShowAuthPickerValidLoginToken() { + public function testShowAuthPickerForbiddenUserClient() { + $this->session->method('get') + ->with('client.flow.v2.login.token') + ->willReturn('loginToken'); + + $this->loginFlowV2Service->method('getByLoginToken') + ->with('loginToken') + ->willThrowException(new LoginFlowV2ClientForbiddenException()); + + $result = $this->controller->showAuthPickerPage(); + + $this->assertInstanceOf(StandaloneTemplateResponse::class, $result); + $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); + $this->assertSame('Please use original client', $result->getParams()['message']); + } + + public function testShowAuthPickerValidLoginToken(): void { $this->session->method('get') ->with('client.flow.v2.login.token') ->willReturn('loginToken'); @@ -178,7 +186,7 @@ class ClientFlowLoginV2ControllerTest extends TestCase { ->willReturn($flow); $this->random->method('generate') - ->with(64, ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_DIGITS) + ->with(64, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS) ->willReturn('random'); $this->session->expects($this->once()) ->method('set') @@ -193,7 +201,7 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); } - public function testGrantPageInvalidStateToken() { + public function testGrantPageInvalidStateToken(): void { $this->session->method('get') ->willReturnCallback(function ($name) { return null; @@ -203,7 +211,7 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); } - public function testGrantPageInvalidLoginToken() { + public function testGrantPageInvalidLoginToken(): void { $this->session->method('get') ->willReturnCallback(function ($name) { if ($name === 'client.flow.v2.state.token') { @@ -223,7 +231,30 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); } - public function testGrantPageValid() { + public function testGrantPageForbiddenUserClient() { + $this->session->method('get') + ->willReturnCallback(function ($name) { + if ($name === 'client.flow.v2.state.token') { + return 'stateToken'; + } + if ($name === 'client.flow.v2.login.token') { + return 'loginToken'; + } + return null; + }); + + $this->loginFlowV2Service->method('getByLoginToken') + ->with('loginToken') + ->willThrowException(new LoginFlowV2ClientForbiddenException()); + + $result = $this->controller->grantPage('stateToken'); + + $this->assertInstanceOf(StandaloneTemplateResponse::class, $result); + $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); + $this->assertSame('Please use original client', $result->getParams()['message']); + } + + public function testGrantPageValid(): void { $this->session->method('get') ->willReturnCallback(function ($name) { if ($name === 'client.flow.v2.state.token') { @@ -253,7 +284,7 @@ class ClientFlowLoginV2ControllerTest extends TestCase { } - public function testGenerateAppPasswordInvalidStateToken() { + public function testGenerateAppPasswordInvalidStateToken(): void { $this->session->method('get') ->willReturnCallback(function ($name) { return null; @@ -263,7 +294,7 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); } - public function testGenerateAppPassworInvalidLoginToken() { + public function testGenerateAppPassworInvalidLoginToken(): void { $this->session->method('get') ->willReturnCallback(function ($name) { if ($name === 'client.flow.v2.state.token') { @@ -283,7 +314,30 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); } - public function testGenerateAppPassworValid() { + public function testGenerateAppPasswordForbiddenUserClient() { + $this->session->method('get') + ->willReturnCallback(function ($name) { + if ($name === 'client.flow.v2.state.token') { + return 'stateToken'; + } + if ($name === 'client.flow.v2.login.token') { + return 'loginToken'; + } + return null; + }); + + $this->loginFlowV2Service->method('getByLoginToken') + ->with('loginToken') + ->willThrowException(new LoginFlowV2ClientForbiddenException()); + + $result = $this->controller->generateAppPassword('stateToken'); + + $this->assertInstanceOf(StandaloneTemplateResponse::class, $result); + $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); + $this->assertSame('Please use original client', $result->getParams()['message']); + } + + public function testGenerateAppPassworValid(): void { $this->session->method('get') ->willReturnCallback(function ($name) { if ($name === 'client.flow.v2.state.token') { @@ -303,7 +357,7 @@ class ClientFlowLoginV2ControllerTest extends TestCase { $clearedState = false; $clearedLogin = false; $this->session->method('remove') - ->willReturnCallback(function ($name) use (&$clearedLogin, &$clearedState) { + ->willReturnCallback(function ($name) use (&$clearedLogin, &$clearedState): void { if ($name === 'client.flow.v2.state.token') { $clearedState = true; } diff --git a/tests/Core/Controller/ContactsMenuControllerTest.php b/tests/Core/Controller/ContactsMenuControllerTest.php index f51bab0f006..aa20e6726e2 100644 --- a/tests/Core/Controller/ContactsMenuControllerTest.php +++ b/tests/Core/Controller/ContactsMenuControllerTest.php @@ -1,25 +1,8 @@ <?php /** - * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Controller; @@ -52,7 +35,7 @@ class ContactsMenuControllerTest extends TestCase { $this->controller = new ContactsMenuController($request, $this->userSession, $this->contactsManager); } - public function testIndex() { + public function testIndex(): void { $user = $this->createMock(IUser::class); $entries = [ $this->createMock(IEntry::class), @@ -71,7 +54,7 @@ class ContactsMenuControllerTest extends TestCase { $this->assertEquals($entries, $response); } - public function testFindOne() { + public function testFindOne(): void { $user = $this->createMock(IUser::class); $entry = $this->createMock(IEntry::class); $this->userSession->expects($this->once()) @@ -87,7 +70,7 @@ class ContactsMenuControllerTest extends TestCase { $this->assertEquals($entry, $response); } - public function testFindOne404() { + public function testFindOne404(): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->once()) ->method('getUser') diff --git a/tests/Core/Controller/CssControllerTest.php b/tests/Core/Controller/CssControllerTest.php index 9659d76a7cb..b4764d6ea3a 100644 --- a/tests/Core/Controller/CssControllerTest.php +++ b/tests/Core/Controller/CssControllerTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Controller; @@ -73,7 +57,7 @@ class CssControllerTest extends TestCase { ); } - public function testNoCssFolderForApp() { + public function testNoCssFolderForApp(): void { $this->appData->method('getFolder') ->with('myapp') ->willThrowException(new NotFoundException()); @@ -84,7 +68,7 @@ class CssControllerTest extends TestCase { } - public function testNoCssFile() { + public function testNoCssFile(): void { $folder = $this->createMock(ISimpleFolder::class); $this->appData->method('getFolder') ->with('myapp') @@ -98,7 +82,7 @@ class CssControllerTest extends TestCase { $this->assertInstanceOf(NotFoundResponse::class, $result); } - public function testGetFile() { + public function testGetFile(): void { $folder = $this->createMock(ISimpleFolder::class); $file = $this->createMock(ISimpleFile::class); $file->method('getName')->willReturn('my name'); @@ -117,13 +101,12 @@ class CssControllerTest extends TestCase { $expires->setTimestamp(1337); $expires->add(new \DateInterval('PT31536000S')); $expected->addHeader('Expires', $expires->format(\DateTime::RFC1123)); - $expected->addHeader('Pragma', 'cache'); $result = $this->controller->getCss('file.css', 'myapp'); $this->assertEquals($expected, $result); } - public function testGetGzipFile() { + public function testGetGzipFile(): void { $folder = $this->createMock(ISimpleFolder::class); $gzipFile = $this->createMock(ISimpleFile::class); $gzipFile->method('getName')->willReturn('my name'); @@ -147,13 +130,12 @@ class CssControllerTest extends TestCase { $expires->setTimestamp(1337); $expires->add(new \DateInterval('PT31536000S')); $expected->addHeader('Expires', $expires->format(\DateTime::RFC1123)); - $expected->addHeader('Pragma', 'cache'); $result = $this->controller->getCss('file.css', 'myapp'); $this->assertEquals($expected, $result); } - public function testGetGzipFileNotFound() { + public function testGetGzipFileNotFound(): void { $folder = $this->createMock(ISimpleFolder::class); $file = $this->createMock(ISimpleFile::class); $file->method('getName')->willReturn('my name'); @@ -182,7 +164,6 @@ class CssControllerTest extends TestCase { $expires->setTimestamp(1337); $expires->add(new \DateInterval('PT31536000S')); $expected->addHeader('Expires', $expires->format(\DateTime::RFC1123)); - $expected->addHeader('Pragma', 'cache'); $result = $this->controller->getCss('file.css', 'myapp'); $this->assertEquals($expected, $result); diff --git a/tests/Core/Controller/GuestAvatarControllerTest.php b/tests/Core/Controller/GuestAvatarControllerTest.php index 42a00e1618c..66a83098130 100644 --- a/tests/Core/Controller/GuestAvatarControllerTest.php +++ b/tests/Core/Controller/GuestAvatarControllerTest.php @@ -1,9 +1,14 @@ <?php +/** + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ namespace Core\Controller; use OC\Core\Controller\GuestAvatarController; use OCP\AppFramework\Http\FileDisplayResponse; +use OCP\Files\File; use OCP\Files\SimpleFS\ISimpleFile; use OCP\IAvatar; use OCP\IAvatarManager; @@ -35,7 +40,7 @@ class GuestAvatarControllerTest extends \Test\TestCase { private $avatar; /** - * @var \OCP\Files\File|\PHPUnit\Framework\MockObject\MockObject + * @var File|\PHPUnit\Framework\MockObject\MockObject */ private $file; @@ -68,7 +73,7 @@ class GuestAvatarControllerTest extends \Test\TestCase { /** * Tests getAvatar returns the guest avatar. */ - public function testGetAvatar() { + public function testGetAvatar(): void { $this->avatarManager->expects($this->once()) ->method('getGuestAvatar') ->with('Peter') diff --git a/tests/Core/Controller/JsControllerTest.php b/tests/Core/Controller/JsControllerTest.php index 6561d22f264..30bc02e8625 100644 --- a/tests/Core/Controller/JsControllerTest.php +++ b/tests/Core/Controller/JsControllerTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Controller; @@ -73,7 +57,7 @@ class JsControllerTest extends TestCase { ); } - public function testNoCssFolderForApp() { + public function testNoCssFolderForApp(): void { $this->appData->method('getFolder') ->with('myapp') ->willThrowException(new NotFoundException()); @@ -84,7 +68,7 @@ class JsControllerTest extends TestCase { } - public function testNoCssFile() { + public function testNoCssFile(): void { $folder = $this->createMock(ISimpleFolder::class); $this->appData->method('getFolder') ->with('myapp') @@ -98,7 +82,7 @@ class JsControllerTest extends TestCase { $this->assertInstanceOf(NotFoundResponse::class, $result); } - public function testGetFile() { + public function testGetFile(): void { $folder = $this->createMock(ISimpleFolder::class); $file = $this->createMock(ISimpleFile::class); $file->method('getName')->willReturn('my name'); @@ -117,13 +101,12 @@ class JsControllerTest extends TestCase { $expires->setTimestamp(1337); $expires->add(new \DateInterval('PT31536000S')); $expected->addHeader('Expires', $expires->format(\DateTime::RFC1123)); - $expected->addHeader('Pragma', 'cache'); $result = $this->controller->getJs('file.js', 'myapp'); $this->assertEquals($expected, $result); } - public function testGetGzipFile() { + public function testGetGzipFile(): void { $folder = $this->createMock(ISimpleFolder::class); $gzipFile = $this->createMock(ISimpleFile::class); $gzipFile->method('getName')->willReturn('my name'); @@ -147,13 +130,12 @@ class JsControllerTest extends TestCase { $expires->setTimestamp(1337); $expires->add(new \DateInterval('PT31536000S')); $expected->addHeader('Expires', $expires->format(\DateTime::RFC1123)); - $expected->addHeader('Pragma', 'cache'); $result = $this->controller->getJs('file.js', 'myapp'); $this->assertEquals($expected, $result); } - public function testGetGzipFileNotFound() { + public function testGetGzipFileNotFound(): void { $folder = $this->createMock(ISimpleFolder::class); $file = $this->createMock(ISimpleFile::class); $file->method('getName')->willReturn('my name'); @@ -182,7 +164,6 @@ class JsControllerTest extends TestCase { $expires->setTimestamp(1337); $expires->add(new \DateInterval('PT31536000S')); $expected->addHeader('Expires', $expires->format(\DateTime::RFC1123)); - $expected->addHeader('Pragma', 'cache'); $result = $this->controller->getJs('file.js', 'myapp'); $this->assertEquals($expected, $result); diff --git a/tests/Core/Controller/LoginControllerTest.php b/tests/Core/Controller/LoginControllerTest.php index ae033582d3c..18baaf5b08c 100644 --- a/tests/Core/Controller/LoginControllerTest.php +++ b/tests/Core/Controller/LoginControllerTest.php @@ -3,23 +3,9 @@ declare(strict_types=1); /** - * @author Lukas Reschke <lukas@owncloud.com> - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Controller; @@ -29,13 +15,13 @@ use OC\Authentication\Login\LoginData; use OC\Authentication\Login\LoginResult; use OC\Authentication\TwoFactorAuth\Manager; use OC\Core\Controller\LoginController; -use OC\Security\Bruteforce\Throttler; use OC\User\Session; +use OCP\App\IAppManager; use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; use OCP\Defaults; use OCP\IConfig; -use OCP\IInitialStateService; use OCP\IL10N; use OCP\IRequest; use OCP\ISession; @@ -43,6 +29,8 @@ use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserManager; use OCP\Notification\IManager; +use OCP\Security\Bruteforce\IThrottler; +use OCP\Security\ITrustedDomainHelper; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; @@ -74,11 +62,11 @@ class LoginControllerTest extends TestCase { /** @var Defaults|MockObject */ private $defaults; - /** @var Throttler|MockObject */ + /** @var IThrottler|MockObject */ private $throttler; - /** @var IInitialStateService|MockObject */ - private $initialStateService; + /** @var IInitialState|MockObject */ + private $initialState; /** @var \OC\Authentication\WebAuthn\Manager|MockObject */ private $webAuthnManager; @@ -89,6 +77,9 @@ class LoginControllerTest extends TestCase { /** @var IL10N|MockObject */ private $l; + /** @var IAppManager|MockObject */ + private $appManager; + protected function setUp(): void { parent::setUp(); $this->request = $this->createMock(IRequest::class); @@ -99,11 +90,13 @@ class LoginControllerTest extends TestCase { $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->twoFactorManager = $this->createMock(Manager::class); $this->defaults = $this->createMock(Defaults::class); - $this->throttler = $this->createMock(Throttler::class); - $this->initialStateService = $this->createMock(IInitialStateService::class); + $this->throttler = $this->createMock(IThrottler::class); + $this->initialState = $this->createMock(IInitialState::class); $this->webAuthnManager = $this->createMock(\OC\Authentication\WebAuthn\Manager::class); $this->notificationManager = $this->createMock(IManager::class); $this->l = $this->createMock(IL10N::class); + $this->appManager = $this->createMock(IAppManager::class); + $this->l->expects($this->any()) ->method('t') ->willReturnCallback(function ($text, $parameters = []) { @@ -113,6 +106,9 @@ class LoginControllerTest extends TestCase { $this->request->method('getRemoteAddress') ->willReturn('1.2.3.4'); + $this->request->method('getHeader') + ->with('Origin') + ->willReturn('domain.example.com'); $this->throttler->method('getDelay') ->with( $this->equalTo('1.2.3.4'), @@ -129,20 +125,24 @@ class LoginControllerTest extends TestCase { $this->urlGenerator, $this->defaults, $this->throttler, - $this->initialStateService, + $this->initialState, $this->webAuthnManager, $this->notificationManager, - $this->l + $this->l, + $this->appManager, ); } - public function testLogoutWithoutToken() { + public function testLogoutWithoutToken(): void { $this->request ->expects($this->once()) ->method('getCookie') ->with('nc_token') ->willReturn(null); $this->request + ->method('getServerProtocol') + ->willReturn('https'); + $this->request ->expects($this->once()) ->method('isUserAgent') ->willReturn(false); @@ -160,13 +160,16 @@ class LoginControllerTest extends TestCase { $this->assertEquals($expected, $this->loginController->logout()); } - public function testLogoutNoClearSiteData() { + public function testLogoutNoClearSiteData(): void { $this->request ->expects($this->once()) ->method('getCookie') ->with('nc_token') ->willReturn(null); $this->request + ->method('getServerProtocol') + ->willReturn('https'); + $this->request ->expects($this->once()) ->method('isUserAgent') ->willReturn(true); @@ -180,13 +183,16 @@ class LoginControllerTest extends TestCase { $this->assertEquals($expected, $this->loginController->logout()); } - public function testLogoutWithToken() { + public function testLogoutWithToken(): void { $this->request ->expects($this->once()) ->method('getCookie') ->with('nc_token') ->willReturn('MyLoginToken'); $this->request + ->method('getServerProtocol') + ->willReturn('https'); + $this->request ->expects($this->once()) ->method('isUserAgent') ->willReturn(false); @@ -214,7 +220,7 @@ class LoginControllerTest extends TestCase { $this->assertEquals($expected, $this->loginController->logout()); } - public function testShowLoginFormForLoggedInUsers() { + public function testShowLoginFormForLoggedInUsers(): void { $this->userSession ->expects($this->once()) ->method('isLoggedIn') @@ -228,7 +234,7 @@ class LoginControllerTest extends TestCase { $this->assertEquals($expectedResponse, $this->loginController->showLoginForm('', '')); } - public function testShowLoginFormWithErrorsInSession() { + public function testShowLoginFormWithErrorsInSession(): void { $this->userSession ->expects($this->once()) ->method('isLoggedIn') @@ -249,10 +255,9 @@ class LoginControllerTest extends TestCase { ], ] ); - $this->initialStateService->expects($this->exactly(11)) - ->method('provideInitialState') - ->withConsecutive([ - 'core', + + $calls = [ + [ 'loginMessages', [ 'MessageArray1', @@ -260,19 +265,26 @@ class LoginControllerTest extends TestCase { 'This community release of Nextcloud is unsupported and push notifications are limited.', ], ], + [ + 'loginErrors', [ - 'core', - 'loginErrors', - [ - 'ErrorArray1', - 'ErrorArray2', - ], + 'ErrorArray1', + 'ErrorArray2', ], - [ - 'core', - 'loginUsername', - '', - ]); + ], + [ + 'loginUsername', + '', + ] + ]; + $this->initialState->expects($this->exactly(13)) + ->method('provideInitialState') + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + if (!empty($expected)) { + $this->assertEquals($expected, func_get_args()); + } + }); $expectedResponse = new TemplateResponse( 'core', @@ -286,22 +298,30 @@ class LoginControllerTest extends TestCase { $this->assertEquals($expectedResponse, $this->loginController->showLoginForm('', '')); } - public function testShowLoginFormForFlowAuth() { + public function testShowLoginFormForFlowAuth(): void { $this->userSession ->expects($this->once()) ->method('isLoggedIn') ->willReturn(false); - $this->initialStateService->expects($this->exactly(12)) - ->method('provideInitialState') - ->withConsecutive([], [], [], [ - 'core', + $calls = [ + [], [], [], + [ 'loginAutocomplete', false - ], [ - 'core', + ], + [ 'loginRedirectUrl', 'login/flow' - ]); + ], + ]; + $this->initialState->expects($this->exactly(14)) + ->method('provideInitialState') + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + if (!empty($expected)) { + $this->assertEquals($expected, func_get_args()); + } + }); $expectedResponse = new TemplateResponse( 'core', @@ -318,7 +338,7 @@ class LoginControllerTest extends TestCase { /** * @return array */ - public function passwordResetDataProvider(): array { + public static function passwordResetDataProvider(): array { return [ [ true, @@ -331,11 +351,9 @@ class LoginControllerTest extends TestCase { ]; } - /** - * @dataProvider passwordResetDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('passwordResetDataProvider')] public function testShowLoginFormWithPasswordResetOption($canChangePassword, - $expectedResult) { + $expectedResult): void { $this->userSession ->expects($this->once()) ->method('isLoggedIn') @@ -362,17 +380,26 @@ class LoginControllerTest extends TestCase { ->method('get') ->with('LdapUser') ->willReturn($user); - $this->initialStateService->expects($this->exactly(11)) - ->method('provideInitialState') - ->withConsecutive([], [], [ - 'core', + $calls = [ + [], [], + [ 'loginUsername', 'LdapUser' - ], [], [], [], [ - 'core', + ], + [], [], [], + [ 'loginCanResetPassword', $expectedResult - ]); + ], + ]; + $this->initialState->expects($this->exactly(13)) + ->method('provideInitialState') + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + if (!empty($expected)) { + $this->assertEquals($expected, func_get_args()); + } + }); $expectedResponse = new TemplateResponse( 'core', @@ -386,7 +413,7 @@ class LoginControllerTest extends TestCase { $this->assertEquals($expectedResponse, $this->loginController->showLoginForm('LdapUser', '')); } - public function testShowLoginFormForUserNamed0() { + public function testShowLoginFormForUserNamed0(): void { $this->userSession ->expects($this->once()) ->method('isLoggedIn') @@ -412,21 +439,30 @@ class LoginControllerTest extends TestCase { ->method('get') ->with('0') ->willReturn($user); - $this->initialStateService->expects($this->exactly(11)) - ->method('provideInitialState') - ->withConsecutive([], [], [], [ - 'core', + $calls = [ + [], [], [], + [ 'loginAutocomplete', true - ], [], [ - 'core', + ], + [], + [ 'loginResetPasswordLink', false - ], [ - 'core', + ], + [ 'loginCanResetPassword', false - ]); + ], + ]; + $this->initialState->expects($this->exactly(13)) + ->method('provideInitialState') + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + if (!empty($expected)) { + $this->assertEquals($expected, func_get_args()); + } + }); $expectedResponse = new TemplateResponse( 'core', @@ -445,6 +481,8 @@ class LoginControllerTest extends TestCase { $password = 'secret'; $loginPageUrl = '/login?redirect_url=/apps/files'; $loginChain = $this->createMock(LoginChain::class); + $trustedDomainHelper = $this->createMock(ITrustedDomainHelper::class); + $trustedDomainHelper->method('isTrustedUrl')->willReturn(true); $this->request ->expects($this->once()) ->method('passesCSRFCheck') @@ -471,15 +509,17 @@ class LoginControllerTest extends TestCase { $expected = new RedirectResponse($loginPageUrl); $expected->throttle(['user' => 'MyUserName']); - $response = $this->loginController->tryLogin($loginChain, $user, $password, '/apps/files'); + $response = $this->loginController->tryLogin($loginChain, $trustedDomainHelper, $user, $password, '/apps/files'); $this->assertEquals($expected, $response); } - public function testLoginWithValidCredentials() { + public function testLoginWithValidCredentials(): void { $user = 'MyUserName'; $password = 'secret'; $loginChain = $this->createMock(LoginChain::class); + $trustedDomainHelper = $this->createMock(ITrustedDomainHelper::class); + $trustedDomainHelper->method('isTrustedUrl')->willReturn(true); $this->request ->expects($this->once()) ->method('passesCSRFCheck') @@ -500,7 +540,7 @@ class LoginControllerTest extends TestCase { ->willReturn('/default/foo'); $expected = new RedirectResponse('/default/foo'); - $this->assertEquals($expected, $this->loginController->tryLogin($loginChain, $user, $password)); + $this->assertEquals($expected, $this->loginController->tryLogin($loginChain, $trustedDomainHelper, $user, $password)); } public function testLoginWithoutPassedCsrfCheckAndNotLoggedIn(): void { @@ -512,6 +552,8 @@ class LoginControllerTest extends TestCase { $password = 'secret'; $originalUrl = 'another%20url'; $loginChain = $this->createMock(LoginChain::class); + $trustedDomainHelper = $this->createMock(ITrustedDomainHelper::class); + $trustedDomainHelper->method('isTrustedUrl')->willReturn(true); $this->request ->expects($this->once()) ->method('passesCSRFCheck') @@ -525,14 +567,14 @@ class LoginControllerTest extends TestCase { $this->userSession->expects($this->never()) ->method('createRememberMeToken'); - $response = $this->loginController->tryLogin($loginChain, 'Jane', $password, $originalUrl); + $response = $this->loginController->tryLogin($loginChain, $trustedDomainHelper, 'Jane', $password, $originalUrl); $expected = new RedirectResponse(''); $expected->throttle(['user' => 'Jane']); $this->assertEquals($expected, $response); } - public function testLoginWithoutPassedCsrfCheckAndLoggedIn() { + public function testLoginWithoutPassedCsrfCheckAndLoggedIn(): void { /** @var IUser|MockObject $user */ $user = $this->createMock(IUser::class); $user->expects($this->any()) @@ -542,6 +584,8 @@ class LoginControllerTest extends TestCase { $originalUrl = 'another url'; $redirectUrl = 'http://localhost/another url'; $loginChain = $this->createMock(LoginChain::class); + $trustedDomainHelper = $this->createMock(ITrustedDomainHelper::class); + $trustedDomainHelper->method('isTrustedUrl')->willReturn(true); $this->request ->expects($this->once()) ->method('passesCSRFCheck') @@ -563,17 +607,19 @@ class LoginControllerTest extends TestCase { ->with('remember_login_cookie_lifetime') ->willReturn(1234); - $response = $this->loginController->tryLogin($loginChain, 'Jane', $password, $originalUrl); + $response = $this->loginController->tryLogin($loginChain, $trustedDomainHelper, 'Jane', $password, $originalUrl); $expected = new RedirectResponse($redirectUrl); $this->assertEquals($expected, $response); } - public function testLoginWithValidCredentialsAndRedirectUrl() { + public function testLoginWithValidCredentialsAndRedirectUrl(): void { $user = 'MyUserName'; $password = 'secret'; $redirectUrl = 'https://next.cloud/apps/mail'; $loginChain = $this->createMock(LoginChain::class); + $trustedDomainHelper = $this->createMock(ITrustedDomainHelper::class); + $trustedDomainHelper->method('isTrustedUrl')->willReturn(true); $this->request ->expects($this->once()) ->method('passesCSRFCheck') @@ -598,13 +644,15 @@ class LoginControllerTest extends TestCase { ->willReturn($redirectUrl); $expected = new RedirectResponse($redirectUrl); - $response = $this->loginController->tryLogin($loginChain, $user, $password, '/apps/mail'); + $response = $this->loginController->tryLogin($loginChain, $trustedDomainHelper, $user, $password, '/apps/mail'); $this->assertEquals($expected, $response); } - public function testToNotLeakLoginName() { + public function testToNotLeakLoginName(): void { $loginChain = $this->createMock(LoginChain::class); + $trustedDomainHelper = $this->createMock(ITrustedDomainHelper::class); + $trustedDomainHelper->method('isTrustedUrl')->willReturn(true); $this->request ->expects($this->once()) ->method('passesCSRFCheck') @@ -637,6 +685,7 @@ class LoginControllerTest extends TestCase { $response = $this->loginController->tryLogin( $loginChain, + $trustedDomainHelper, 'john@doe.com', 'just wrong', '/apps/files' diff --git a/tests/Core/Controller/LostControllerTest.php b/tests/Core/Controller/LostControllerTest.php index 3f62c522627..bbb5f2c2e54 100644 --- a/tests/Core/Controller/LostControllerTest.php +++ b/tests/Core/Controller/LostControllerTest.php @@ -1,22 +1,8 @@ <?php + /** - * @author Lukas Reschke <lukas@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Controller; @@ -153,7 +139,7 @@ class LostControllerTest extends TestCase { ); } - public function testResetFormTokenError() { + public function testResetFormTokenError(): void { $this->userManager->method('get') ->with('ValidTokenUser') ->willReturn($this->existingUser); @@ -171,10 +157,11 @@ class LostControllerTest extends TestCase { ] ], 'guest'); + $expectedResponse->throttle(); $this->assertEquals($expectedResponse, $response); } - public function testResetFormValidToken() { + public function testResetFormValidToken(): void { $this->userManager->method('get') ->with('ValidTokenUser') ->willReturn($this->existingUser); @@ -186,13 +173,18 @@ class LostControllerTest extends TestCase { ->method('linkToRouteAbsolute') ->with('core.lost.setPassword', ['userId' => 'ValidTokenUser', 'token' => 'MySecretToken']) ->willReturn('https://example.tld/index.php/lostpassword/set/sometoken/someuser'); + + $calls = [ + ['resetPasswordUser', 'ValidTokenUser'], + ['resetPasswordTarget', 'https://example.tld/index.php/lostpassword/set/sometoken/someuser'], + ]; $this->initialState ->expects($this->exactly(2)) ->method('provideInitialState') - ->withConsecutive( - ['resetPasswordUser', 'ValidTokenUser'], - ['resetPasswordTarget', 'https://example.tld/index.php/lostpassword/set/sometoken/someuser'] - ); + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, func_get_args()); + }); $response = $this->lostController->resetform('MySecretToken', 'ValidTokenUser'); $expectedResponse = new TemplateResponse('core', @@ -202,7 +194,7 @@ class LostControllerTest extends TestCase { $this->assertEquals($expectedResponse, $response); } - public function testEmailUnsuccessful() { + public function testEmailUnsuccessful(): void { $existingUser = 'ExistingUser'; $nonExistingUser = 'NonExistingUser'; $this->userManager @@ -244,12 +236,12 @@ class LostControllerTest extends TestCase { $this->assertEquals($expectedResponse, $response); } - public function testEmailSuccessful() { + public function testEmailSuccessful(): void { $this->userManager - ->expects($this->any()) - ->method('get') - ->with('ExistingUser') - ->willReturn($this->existingUser); + ->expects($this->any()) + ->method('get') + ->with('ExistingUser') + ->willReturn($this->existingUser); $this->verificationToken->expects($this->once()) ->method('create') ->willReturn('ThisIsMaybeANotSoSecretToken!'); @@ -301,17 +293,17 @@ class LostControllerTest extends TestCase { $this->assertEquals($expectedResponse, $response); } - public function testEmailWithMailSuccessful() { + public function testEmailWithMailSuccessful(): void { $this->userManager - ->expects($this->any()) - ->method('get') - ->with('test@example.com') - ->willReturn(null); + ->expects($this->any()) + ->method('get') + ->with('test@example.com') + ->willReturn(null); $this->userManager - ->expects($this->any()) - ->method('getByEmail') - ->with('test@example.com') - ->willReturn([$this->existingUser]); + ->expects($this->any()) + ->method('getByEmail') + ->with('test@example.com') + ->willReturn([$this->existingUser]); $this->verificationToken->expects($this->once()) ->method('create') ->willReturn('ThisIsMaybeANotSoSecretToken!'); @@ -363,12 +355,12 @@ class LostControllerTest extends TestCase { $this->assertEquals($expectedResponse, $response); } - public function testEmailCantSendException() { + public function testEmailCantSendException(): void { $this->userManager - ->expects($this->any()) - ->method('get') - ->with('ExistingUser') - ->willReturn($this->existingUser); + ->expects($this->any()) + ->method('get') + ->with('ExistingUser') + ->willReturn($this->existingUser); $this->verificationToken->expects($this->once()) ->method('create') ->willReturn('ThisIsMaybeANotSoSecretToken!'); @@ -412,7 +404,7 @@ class LostControllerTest extends TestCase { ->expects($this->once()) ->method('send') ->with($message) - ->will($this->throwException(new \Exception())); + ->willThrowException(new \Exception()); $this->logger->expects($this->exactly(1)) ->method('error'); @@ -423,7 +415,7 @@ class LostControllerTest extends TestCase { $this->assertEquals($expectedResponse, $response); } - public function testSetPasswordUnsuccessful() { + public function testSetPasswordUnsuccessful(): void { $this->config->method('getUserValue') ->with('ValidTokenUser', 'core', 'lostpassword', null) ->willReturn('encryptedData'); @@ -446,10 +438,10 @@ class LostControllerTest extends TestCase { $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', true); $expectedResponse = ['status' => 'error', 'msg' => '']; - $this->assertSame($expectedResponse, $response); + $this->assertSame($expectedResponse, $response->getData()); } - public function testSetPasswordSuccessful() { + public function testSetPasswordSuccessful(): void { $this->config->method('getUserValue') ->with('ValidTokenUser', 'core', 'lostpassword', null) ->willReturn('encryptedData'); @@ -462,22 +454,29 @@ class LostControllerTest extends TestCase { $this->userManager->method('get') ->with('ValidTokenUser') ->willReturn($this->existingUser); - $beforePasswordResetEvent = new BeforePasswordResetEvent($this->existingUser, 'NewPassword'); - $passwordResetEvent = new PasswordResetEvent($this->existingUser, 'NewPassword'); + + $calls = [ + [new BeforePasswordResetEvent($this->existingUser, 'NewPassword')], + [new PasswordResetEvent($this->existingUser, 'NewPassword')], + ]; $this->eventDispatcher ->expects($this->exactly(2)) ->method('dispatchTyped') - ->withConsecutive([$beforePasswordResetEvent], [$passwordResetEvent]); + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, func_get_args()); + }); + $this->config->expects($this->once()) ->method('deleteUserValue') ->with('ValidTokenUser', 'core', 'lostpassword'); $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', true); $expectedResponse = ['user' => 'ValidTokenUser', 'status' => 'success']; - $this->assertSame($expectedResponse, $response); + $this->assertSame($expectedResponse, $response->getData()); } - public function testSetPasswordExpiredToken() { + public function testSetPasswordExpiredToken(): void { $this->config->method('getUserValue') ->with('ValidTokenUser', 'core', 'lostpassword', null) ->willReturn('encryptedData'); @@ -493,10 +492,10 @@ class LostControllerTest extends TestCase { 'status' => 'error', 'msg' => 'Could not reset password because the token is expired', ]; - $this->assertSame($expectedResponse, $response); + $this->assertSame($expectedResponse, $response->getData()); } - public function testSetPasswordInvalidDataInDb() { + public function testSetPasswordInvalidDataInDb(): void { $this->config->method('getUserValue') ->with('ValidTokenUser', 'core', 'lostpassword', null) ->willReturn('invalidEncryptedData'); @@ -513,10 +512,10 @@ class LostControllerTest extends TestCase { 'status' => 'error', 'msg' => 'Could not reset password because the token is invalid', ]; - $this->assertSame($expectedResponse, $response); + $this->assertSame($expectedResponse, $response->getData()); } - public function testIsSetPasswordWithoutTokenFailing() { + public function testIsSetPasswordWithoutTokenFailing(): void { $this->config->method('getUserValue') ->with('ValidTokenUser', 'core', 'lostpassword', null) ->willReturn('aValidtoken'); @@ -532,10 +531,10 @@ class LostControllerTest extends TestCase { 'status' => 'error', 'msg' => 'Could not reset password because the token is invalid' ]; - $this->assertSame($expectedResponse, $response); + $this->assertSame($expectedResponse, $response->getData()); } - public function testSetPasswordForDisabledUser() { + public function testSetPasswordForDisabledUser(): void { $user = $this->createMock(IUser::class); $user->expects($this->any()) ->method('isEnabled') @@ -562,10 +561,10 @@ class LostControllerTest extends TestCase { 'status' => 'error', 'msg' => 'Could not reset password because the token is invalid' ]; - $this->assertSame($expectedResponse, $response); + $this->assertSame($expectedResponse, $response->getData()); } - public function testSendEmailNoEmail() { + public function testSendEmailNoEmail(): void { $user = $this->createMock(IUser::class); $user->expects($this->any()) ->method('isEnabled') @@ -588,7 +587,7 @@ class LostControllerTest extends TestCase { $this->assertEquals($expectedResponse, $response); } - public function testSetPasswordEncryptionDontProceedPerUserKey() { + public function testSetPasswordEncryptionDontProceedPerUserKey(): void { /** @var IEncryptionModule|MockObject $encryptionModule */ $encryptionModule = $this->createMock(IEncryptionModule::class); $encryptionModule->expects($this->once())->method('needDetailedAccessList')->willReturn(true); @@ -598,10 +597,10 @@ class LostControllerTest extends TestCase { }]]); $response = $this->lostController->setPassword('myToken', 'user', 'newpass', false); $expectedResponse = ['status' => 'error', 'msg' => '', 'encryption' => true]; - $this->assertSame($expectedResponse, $response); + $this->assertSame($expectedResponse, $response->getData()); } - public function testSetPasswordDontProceedMasterKey() { + public function testSetPasswordDontProceedMasterKey(): void { $encryptionModule = $this->createMock(IEncryptionModule::class); $encryptionModule->expects($this->once())->method('needDetailedAccessList')->willReturn(false); $this->encryptionManager->expects($this->once())->method('getEncryptionModules') @@ -626,10 +625,10 @@ class LostControllerTest extends TestCase { $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', false); $expectedResponse = ['user' => 'ValidTokenUser', 'status' => 'success']; - $this->assertSame($expectedResponse, $response); + $this->assertSame($expectedResponse, $response->getData()); } - public function testTwoUsersWithSameEmail() { + public function testTwoUsersWithSameEmail(): void { $user1 = $this->createMock(IUser::class); $user1->expects($this->any()) ->method('getEMailAddress') @@ -680,18 +679,18 @@ class LostControllerTest extends TestCase { /** * @return array */ - public function dataTwoUserswithSameEmailOneDisabled(): array { + public static function dataTwoUsersWithSameEmailOneDisabled(): array { return [ - ['user1' => true, 'user2' => false], - ['user1' => false, 'user2' => true] + ['userEnabled1' => true, 'userEnabled2' => false], + ['userEnabled1' => false, 'userEnabled2' => true] ]; } /** - * @dataProvider dataTwoUserswithSameEmailOneDisabled * @param bool $userEnabled1 * @param bool $userEnabled2 */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataTwoUsersWithSameEmailOneDisabled')] public function testTwoUsersWithSameEmailOneDisabled(bool $userEnabled1, bool $userEnabled2): void { $user1 = $this->createMock(IUser::class); $user1->method('getEMailAddress') @@ -720,4 +719,38 @@ class LostControllerTest extends TestCase { $result = self::invokePrivate($this->lostController, 'findUserByIdOrMail', ['test@example.com']); $this->assertInstanceOf(IUser::class, $result); } + + public function testTrimEmailInput(): void { + $this->userManager + ->expects($this->once()) + ->method('getByEmail') + ->with('test@example.com') + ->willReturn([$this->existingUser]); + + $this->mailer + ->expects($this->once()) + ->method('send'); + + $response = $this->lostController->email(' test@example.com '); + $expectedResponse = new JSONResponse(['status' => 'success']); + $expectedResponse->throttle(); + $this->assertEquals($expectedResponse, $response); + } + + public function testUsernameInput(): void { + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->willReturn($this->existingUser); + + $this->mailer + ->expects($this->once()) + ->method('send'); + + $response = $this->lostController->email(' ExistingUser '); + $expectedResponse = new JSONResponse(['status' => 'success']); + $expectedResponse->throttle(); + $this->assertEquals($expectedResponse, $response); + } } diff --git a/tests/Core/Controller/NavigationControllerTest.php b/tests/Core/Controller/NavigationControllerTest.php index ddf307ec06d..d00976f18ec 100644 --- a/tests/Core/Controller/NavigationControllerTest.php +++ b/tests/Core/Controller/NavigationControllerTest.php @@ -1,30 +1,13 @@ <?php + /** - * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net> - * - * @author Julius Härtl <jus@bitgrid.net> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Controller; use OC\Core\Controller\NavigationController; -use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\INavigationManager; use OCP\IRequest; @@ -59,13 +42,14 @@ class NavigationControllerTest extends TestCase { ); } - public function dataGetNavigation() { + public static function dataGetNavigation(): array { return [ - [false], [true] + [false], + [true], ]; } - /** @dataProvider dataGetNavigation */ - public function testGetAppNavigation($absolute) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetNavigation')] + public function testGetAppNavigation(bool $absolute): void { $this->navigationManager->expects($this->once()) ->method('getAll') ->with('link') @@ -76,11 +60,10 @@ class NavigationControllerTest extends TestCase { ->willReturn('http://localhost/'); $this->urlGenerator->expects($this->exactly(2)) ->method('getAbsoluteURL') - ->withConsecutive(['/index.php/apps/files'], ['icon']) - ->willReturnOnConsecutiveCalls( - 'http://localhost/index.php/apps/files', - 'http://localhost/icon' - ); + ->willReturnMap([ + ['/index.php/apps/files', 'http://localhost/index.php/apps/files'], + ['icon', 'http://localhost/icon'], + ]); $actual = $this->controller->getAppsNavigation($absolute); $this->assertInstanceOf(DataResponse::class, $actual); $this->assertEquals('http://localhost/index.php/apps/files', $actual->getData()[0]['href']); @@ -93,8 +76,8 @@ class NavigationControllerTest extends TestCase { } } - /** @dataProvider dataGetNavigation */ - public function testGetSettingsNavigation($absolute) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetNavigation')] + public function testGetSettingsNavigation(bool $absolute): void { $this->navigationManager->expects($this->once()) ->method('getAll') ->with('settings') @@ -105,14 +88,10 @@ class NavigationControllerTest extends TestCase { ->willReturn('http://localhost/'); $this->urlGenerator->expects($this->exactly(2)) ->method('getAbsoluteURL') - ->withConsecutive( - ['/index.php/settings/user'], - ['/core/img/settings.svg'] - ) - ->willReturnOnConsecutiveCalls( - 'http://localhost/index.php/settings/user', - 'http://localhost/core/img/settings.svg' - ); + ->willReturnMap([ + ['/index.php/settings/user', 'http://localhost/index.php/settings/user'], + ['/core/img/settings.svg', 'http://localhost/core/img/settings.svg'] + ]); $actual = $this->controller->getSettingsNavigation($absolute); $this->assertInstanceOf(DataResponse::class, $actual); $this->assertEquals('http://localhost/index.php/settings/user', $actual->getData()[0]['href']); @@ -125,33 +104,35 @@ class NavigationControllerTest extends TestCase { } } - public function testGetAppNavigationEtagMatch() { - $navigation = [ ['id' => 'files', 'href' => '/index.php/apps/files', 'icon' => 'icon' ] ]; - $this->request->expects($this->once()) - ->method('getHeader') - ->with('If-None-Match') - ->willReturn(md5(json_encode($navigation))); - $this->navigationManager->expects($this->once()) + public function testEtagIgnoresLogout(): void { + $navigation1 = [ + ['id' => 'files', 'href' => '/index.php/apps/files', 'icon' => 'icon' ], + ['id' => 'logout', 'href' => '/index.php/logout?requesttoken=abcd', 'icon' => 'icon' ], + ]; + $navigation2 = [ + ['id' => 'files', 'href' => '/index.php/apps/files', 'icon' => 'icon' ], + ['id' => 'logout', 'href' => '/index.php/logout?requesttoken=1234', 'icon' => 'icon' ], + ]; + $navigation3 = [ + ['id' => 'files', 'href' => '/index.php/apps/files/test', 'icon' => 'icon' ], + ['id' => 'logout', 'href' => '/index.php/logout?requesttoken=1234', 'icon' => 'icon' ], + ]; + $this->navigationManager->expects($this->exactly(3)) ->method('getAll') ->with('link') - ->willReturn($navigation); - $actual = $this->controller->getAppsNavigation(); - $this->assertInstanceOf(DataResponse::class, $actual); - $this->assertEquals(Http::STATUS_NOT_MODIFIED, $actual->getStatus()); - } + ->willReturnOnConsecutiveCalls( + $navigation1, + $navigation2, + $navigation3, + ); - public function testGetSettingsNavigationEtagMatch() { - $navigation = [ ['id' => 'logout', 'href' => '/index.php/apps/files', 'icon' => 'icon' ] ]; - $this->request->expects($this->once()) - ->method('getHeader') - ->with('If-None-Match') - ->willReturn(md5(json_encode([ ['id' => 'logout', 'href' => 'logout', 'icon' => 'icon' ] ]))); - $this->navigationManager->expects($this->once()) - ->method('getAll') - ->with('settings') - ->willReturn($navigation); - $actual = $this->controller->getSettingsNavigation(); - $this->assertInstanceOf(DataResponse::class, $actual); - $this->assertEquals(Http::STATUS_NOT_MODIFIED, $actual->getStatus()); + // Changes in the logout url should not change the ETag + $request1 = $this->controller->getAppsNavigation(); + $request2 = $this->controller->getAppsNavigation(); + $this->assertEquals($request1->getETag(), $request2->getETag()); + + // Changes in non-logout urls should result in a different ETag + $request3 = $this->controller->getAppsNavigation(); + $this->assertNotEquals($request2->getETag(), $request3->getETag()); } } diff --git a/tests/Core/Controller/OCSControllerTest.php b/tests/Core/Controller/OCSControllerTest.php index 61ed4a50d62..bd7e26d5e8f 100644 --- a/tests/Core/Controller/OCSControllerTest.php +++ b/tests/Core/Controller/OCSControllerTest.php @@ -1,24 +1,9 @@ <?php + /** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OC\Core\Controller; @@ -31,6 +16,8 @@ use OCP\IRequest; use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; +use OCP\Server; +use OCP\ServerVersion; use Test\TestCase; class OCSControllerTest extends TestCase { @@ -44,6 +31,8 @@ class OCSControllerTest extends TestCase { private $userManager; /** @var Manager|\PHPUnit\Framework\MockObject\MockObject */ private $keyManager; + /** @var ServerVersion|\PHPUnit\Framework\MockObject\MockObject */ + private $serverVersion; /** @var OCSController */ private $controller; @@ -55,6 +44,7 @@ class OCSControllerTest extends TestCase { $this->userSession = $this->createMock(IUserSession::class); $this->userManager = $this->createMock(IUserManager::class); $this->keyManager = $this->createMock(Manager::class); + $serverVersion = Server::get(ServerVersion::class); $this->controller = new OCSController( 'core', @@ -62,7 +52,8 @@ class OCSControllerTest extends TestCase { $this->capabilitiesManager, $this->userSession, $this->userManager, - $this->keyManager + $this->keyManager, + $serverVersion ); } @@ -84,18 +75,19 @@ class OCSControllerTest extends TestCase { return new DataResponse($data); } - public function testGetCapabilities() { + public function testGetCapabilities(): void { $this->userSession->expects($this->once()) ->method('isLoggedIn') ->willReturn(true); - [$major, $minor, $micro] = \OCP\Util::getVersion(); + + $serverVersion = Server::get(ServerVersion::class); $result = []; $result['version'] = [ - 'major' => $major, - 'minor' => $minor, - 'micro' => $micro, - 'string' => \OC_Util::getVersionString(), + 'major' => $serverVersion->getMajorVersion(), + 'minor' => $serverVersion->getMinorVersion(), + 'micro' => $serverVersion->getPatchVersion(), + 'string' => $serverVersion->getVersionString(), 'edition' => '', 'extendedSupport' => false ]; @@ -117,18 +109,18 @@ class OCSControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->getCapabilities()); } - public function testGetCapabilitiesPublic() { + public function testGetCapabilitiesPublic(): void { $this->userSession->expects($this->once()) ->method('isLoggedIn') ->willReturn(false); - [$major, $minor, $micro] = \OCP\Util::getVersion(); + $serverVersion = Server::get(ServerVersion::class); $result = []; $result['version'] = [ - 'major' => $major, - 'minor' => $minor, - 'micro' => $micro, - 'string' => \OC_Util::getVersionString(), + 'major' => $serverVersion->getMajorVersion(), + 'minor' => $serverVersion->getMinorVersion(), + 'micro' => $serverVersion->getPatchVersion(), + 'string' => $serverVersion->getVersionString(), 'edition' => '', 'extendedSupport' => false ]; @@ -151,7 +143,7 @@ class OCSControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->getCapabilities()); } - public function testPersonCheckValid() { + public function testPersonCheckValid(): void { $this->userManager->method('checkPassword') ->with( $this->equalTo('user'), @@ -166,7 +158,7 @@ class OCSControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->personCheck('user', 'pass')); } - public function testPersonInvalid() { + public function testPersonInvalid(): void { $this->userManager->method('checkPassword') ->with( $this->equalTo('user'), @@ -178,7 +170,7 @@ class OCSControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->personCheck('user', 'wrongpass')); } - public function testPersonNoLogin() { + public function testPersonNoLogin(): void { $this->userManager->method('checkPassword') ->with( $this->equalTo('user'), @@ -189,18 +181,18 @@ class OCSControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->personCheck('', '')); } - public function testGetIdentityProofWithNotExistingUser() { + public function testGetIdentityProofWithNotExistingUser(): void { $this->userManager ->expects($this->once()) ->method('get') ->with('NotExistingUser') ->willReturn(null); - $expected = new DataResponse(['User not found'], 404); + $expected = new DataResponse(['Account not found'], 404); $this->assertEquals($expected, $this->controller->getIdentityProof('NotExistingUser')); } - public function testGetIdentityProof() { + public function testGetIdentityProof(): void { $user = $this->createMock(IUser::class); $key = $this->createMock(Key::class); $this->userManager diff --git a/tests/Core/Controller/PreviewControllerTest.php b/tests/Core/Controller/PreviewControllerTest.php index 7815505d5a8..5a6cd1fba0a 100644 --- a/tests/Core/Controller/PreviewControllerTest.php +++ b/tests/Core/Controller/PreviewControllerTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Controller; @@ -26,68 +10,68 @@ namespace Tests\Core\Controller; use OC\Core\Controller\PreviewController; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; -use OCP\AppFramework\Utility\ITimeFactory; use OCP\Files\File; use OCP\Files\Folder; use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; use OCP\Files\SimpleFS\ISimpleFile; +use OCP\Files\Storage\ISharedStorage; use OCP\Files\Storage\IStorage; use OCP\IPreview; use OCP\IRequest; +use OCP\Preview\IMimeIconProvider; +use OCP\Share\IShare; +use PHPUnit\Framework\MockObject\MockObject; class PreviewControllerTest extends \Test\TestCase { - /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */ - private $rootFolder; - - /** @var string */ - private $userId; - /** @var IPreview|\PHPUnit\Framework\MockObject\MockObject */ - private $previewManager; + private string $userId; + private PreviewController $controller; - /** @var PreviewController|\PHPUnit\Framework\MockObject\MockObject */ - private $controller; + private IRootFolder&MockObject $rootFolder; + private IPreview&MockObject $previewManager; + private IRequest&MockObject $request; protected function setUp(): void { parent::setUp(); - $this->rootFolder = $this->createMock(IRootFolder::class); $this->userId = 'user'; + $this->rootFolder = $this->createMock(IRootFolder::class); $this->previewManager = $this->createMock(IPreview::class); + $this->request = $this->createMock(IRequest::class); $this->controller = new PreviewController( 'core', - $this->createMock(IRequest::class), + $this->request, $this->previewManager, $this->rootFolder, $this->userId, - $this->createMock(ITimeFactory::class) + $this->createMock(IMimeIconProvider::class) ); } - public function testInvalidFile() { + public function testInvalidFile(): void { $res = $this->controller->getPreview(''); $expected = new DataResponse([], Http::STATUS_BAD_REQUEST); $this->assertEquals($expected, $res); } - public function testInvalidWidth() { + public function testInvalidWidth(): void { $res = $this->controller->getPreview('file', 0); $expected = new DataResponse([], Http::STATUS_BAD_REQUEST); $this->assertEquals($expected, $res); } - public function testInvalidHeight() { + public function testInvalidHeight(): void { $res = $this->controller->getPreview('file', 10, 0); $expected = new DataResponse([], Http::STATUS_BAD_REQUEST); $this->assertEquals($expected, $res); } - public function testFileNotFound() { + public function testFileNotFound(): void { $userFolder = $this->createMock(Folder::class); $this->rootFolder->method('getUserFolder') ->with($this->equalTo($this->userId)) @@ -103,7 +87,7 @@ class PreviewControllerTest extends \Test\TestCase { $this->assertEquals($expected, $res); } - public function testNotAFile() { + public function testNotAFile(): void { $userFolder = $this->createMock(Folder::class); $this->rootFolder->method('getUserFolder') ->with($this->equalTo($this->userId)) @@ -120,7 +104,7 @@ class PreviewControllerTest extends \Test\TestCase { $this->assertEquals($expected, $res); } - public function testNoPreviewAndNoIcon() { + public function testNoPreviewAndNoIcon(): void { $userFolder = $this->createMock(Folder::class); $this->rootFolder->method('getUserFolder') ->with($this->equalTo($this->userId)) @@ -141,7 +125,38 @@ class PreviewControllerTest extends \Test\TestCase { $this->assertEquals($expected, $res); } - public function testForbiddenFile() { + public function testNoPreview() { + $userFolder = $this->createMock(Folder::class); + $this->rootFolder->method('getUserFolder') + ->with($this->equalTo($this->userId)) + ->willReturn($userFolder); + + $file = $this->createMock(File::class); + $userFolder->method('get') + ->with($this->equalTo('file')) + ->willReturn($file); + + $storage = $this->createMock(IStorage::class); + $file->method('getStorage') + ->willReturn($storage); + + $this->previewManager->method('isAvailable') + ->with($this->equalTo($file)) + ->willReturn(true); + + $file->method('isReadable') + ->willReturn(true); + + $this->previewManager->method('getPreview') + ->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode')) + ->willThrowException(new NotFoundException()); + + $res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode'); + $expected = new DataResponse([], Http::STATUS_NOT_FOUND); + + $this->assertEquals($expected, $res); + } + public function testFileWithoutReadPermission() { $userFolder = $this->createMock(Folder::class); $this->rootFolder->method('getUserFolder') ->with($this->equalTo($this->userId)) @@ -165,45 +180,107 @@ class PreviewControllerTest extends \Test\TestCase { $this->assertEquals($expected, $res); } - public function testNoPreview() { + public function testFileWithoutDownloadPermission() { $userFolder = $this->createMock(Folder::class); $this->rootFolder->method('getUserFolder') ->with($this->equalTo($this->userId)) ->willReturn($userFolder); $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); $userFolder->method('get') ->with($this->equalTo('file')) ->willReturn($file); - $storage = $this->createMock(IStorage::class); + $this->previewManager->method('isAvailable') + ->with($this->equalTo($file)) + ->willReturn(true); + + $share = $this->createMock(IShare::class); + $share->method('canSeeContent') + ->willReturn(false); + + $storage = $this->createMock(ISharedStorage::class); + $storage->method('instanceOfStorage') + ->with(ISharedStorage::class) + ->willReturn(true); + $storage->method('getShare') + ->willReturn($share); + $file->method('getStorage') ->willReturn($storage); + $file->method('isReadable') + ->willReturn(true); + + $this->request->method('getHeader')->willReturn(''); + + $res = $this->controller->getPreview('file', 10, 10, true, true); + $expected = new DataResponse([], Http::STATUS_FORBIDDEN); + + $this->assertEquals($expected, $res); + } + + public function testFileWithoutDownloadPermissionButHeader() { + $userFolder = $this->createMock(Folder::class); + $this->rootFolder->method('getUserFolder') + ->with($this->equalTo($this->userId)) + ->willReturn($userFolder); + + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); + $userFolder->method('get') + ->with($this->equalTo('file')) + ->willReturn($file); $this->previewManager->method('isAvailable') ->with($this->equalTo($file)) ->willReturn(true); + $share = $this->createMock(IShare::class); + $share->method('canSeeContent') + ->willReturn(false); + + $storage = $this->createMock(ISharedStorage::class); + $storage->method('instanceOfStorage') + ->with(ISharedStorage::class) + ->willReturn(true); + $storage->method('getShare') + ->willReturn($share); + + $file->method('getStorage') + ->willReturn($storage); $file->method('isReadable') ->willReturn(true); + $this->request + ->method('getHeader') + ->with('x-nc-preview') + ->willReturn('true'); + + $preview = $this->createMock(ISimpleFile::class); + $preview->method('getName')->willReturn('my name'); + $preview->method('getMTime')->willReturn(42); $this->previewManager->method('getPreview') ->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode')) - ->willThrowException(new NotFoundException()); + ->willReturn($preview); + $preview->method('getMimeType') + ->willReturn('myMime'); $res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode'); - $expected = new DataResponse([], Http::STATUS_NOT_FOUND); - $this->assertEquals($expected, $res); + $this->assertEquals('myMime', $res->getHeaders()['Content-Type']); + $this->assertEquals(Http::STATUS_OK, $res->getStatus()); + $this->assertEquals($preview, $this->invokePrivate($res, 'file')); } - public function testValidPreview() { + public function testValidPreview(): void { $userFolder = $this->createMock(Folder::class); $this->rootFolder->method('getUserFolder') ->with($this->equalTo($this->userId)) ->willReturn($userFolder); $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); $userFolder->method('get') ->with($this->equalTo('file')) ->willReturn($file); @@ -234,4 +311,57 @@ class PreviewControllerTest extends \Test\TestCase { $this->assertEquals(Http::STATUS_OK, $res->getStatus()); $this->assertEquals($preview, $this->invokePrivate($res, 'file')); } + + public function testValidPreviewOfShare() { + $userFolder = $this->createMock(Folder::class); + $this->rootFolder->method('getUserFolder') + ->with($this->equalTo($this->userId)) + ->willReturn($userFolder); + + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); + $userFolder->method('get') + ->with($this->equalTo('file')) + ->willReturn($file); + + $this->previewManager->method('isAvailable') + ->with($this->equalTo($file)) + ->willReturn(true); + + // No attributes set -> download permitted + $share = $this->createMock(IShare::class); + $share->method('canSeeContent') + ->willReturn(true); + + $storage = $this->createMock(ISharedStorage::class); + $storage->method('instanceOfStorage') + ->with(ISharedStorage::class) + ->willReturn(true); + $storage->method('getShare') + ->willReturn($share); + + $file->method('getStorage') + ->willReturn($storage); + $file->method('isReadable') + ->willReturn(true); + + $this->request + ->method('getHeader') + ->willReturn(''); + + $preview = $this->createMock(ISimpleFile::class); + $preview->method('getName')->willReturn('my name'); + $preview->method('getMTime')->willReturn(42); + $this->previewManager->method('getPreview') + ->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode')) + ->willReturn($preview); + $preview->method('getMimeType') + ->willReturn('myMime'); + + $res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode'); + + $this->assertEquals('myMime', $res->getHeaders()['Content-Type']); + $this->assertEquals(Http::STATUS_OK, $res->getStatus()); + $this->assertEquals($preview, $this->invokePrivate($res, 'file')); + } } diff --git a/tests/Core/Controller/TwoFactorChallengeControllerTest.php b/tests/Core/Controller/TwoFactorChallengeControllerTest.php index baf7feaa068..d9ea1ca263f 100644 --- a/tests/Core/Controller/TwoFactorChallengeControllerTest.php +++ b/tests/Core/Controller/TwoFactorChallengeControllerTest.php @@ -1,23 +1,9 @@ <?php /** - * @author Christoph Wurst <christoph@owncloud.com> - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Test\Core\Controller; @@ -36,7 +22,7 @@ use OCP\ISession; use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserSession; -use OCP\Template; +use OCP\Template\ITemplate; use Psr\Log\LoggerInterface; use Test\TestCase; @@ -82,14 +68,14 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->urlGenerator, $this->logger, ]) - ->setMethods(['getLogoutUrl']) + ->onlyMethods(['getLogoutUrl']) ->getMock(); $this->controller->expects($this->any()) ->method('getLogoutUrl') ->willReturn('logoutAttribute'); } - public function testSelectChallenge() { + public function testSelectChallenge(): void { $user = $this->getMockBuilder(IUser::class)->getMock(); $p1 = $this->createMock(IActivatableAtLogin::class); $p1->method('getId')->willReturn('p1'); @@ -123,13 +109,13 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->selectChallenge('/some/url')); } - public function testShowChallenge() { + public function testShowChallenge(): void { $user = $this->createMock(IUser::class); $provider = $this->createMock(IProvider::class); $provider->method('getId')->willReturn('myprovider'); $backupProvider = $this->createMock(IProvider::class); $backupProvider->method('getId')->willReturn('backup_codes'); - $tmpl = $this->createMock(Template::class); + $tmpl = $this->createMock(ITemplate::class); $providerSet = new ProviderSet([$provider, $backupProvider], true); $this->userSession->expects($this->once()) @@ -174,7 +160,7 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->showChallenge('myprovider', '/re/dir/ect/url')); } - public function testShowInvalidChallenge() { + public function testShowInvalidChallenge(): void { $user = $this->createMock(IUser::class); $providerSet = new ProviderSet([], false); @@ -195,7 +181,7 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->showChallenge('myprovider', 'redirect/url')); } - public function testSolveChallenge() { + public function testSolveChallenge(): void { $user = $this->createMock(IUser::class); $provider = $this->createMock(IProvider::class); @@ -220,7 +206,7 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token')); } - public function testSolveValidChallengeAndRedirect() { + public function testSolveValidChallengeAndRedirect(): void { $user = $this->createMock(IUser::class); $provider = $this->createMock(IProvider::class); @@ -245,7 +231,7 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token', 'redirect%20url')); } - public function testSolveChallengeInvalidProvider() { + public function testSolveChallengeInvalidProvider(): void { $user = $this->getMockBuilder(IUser::class)->getMock(); $this->userSession->expects($this->once()) @@ -265,7 +251,7 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token')); } - public function testSolveInvalidChallenge() { + public function testSolveInvalidChallenge(): void { $user = $this->createMock(IUser::class); $provider = $this->createMock(IProvider::class); @@ -299,10 +285,10 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token', '/url')); } - public function testSolveChallengeTwoFactorException() { + public function testSolveChallengeTwoFactorException(): void { $user = $this->createMock(IUser::class); $provider = $this->createMock(IProvider::class); - $exception = new TwoFactorException("2FA failed"); + $exception = new TwoFactorException('2FA failed'); $this->userSession->expects($this->once()) ->method('getUser') @@ -315,13 +301,17 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->twoFactorManager->expects($this->once()) ->method('verifyChallenge') ->with('myprovider', $user, 'token') - ->will($this->throwException($exception)); + ->willThrowException($exception); + $calls = [ + ['two_factor_auth_error_message', '2FA failed'], + ['two_factor_auth_error', true], + ]; $this->session->expects($this->exactly(2)) ->method('set') - ->withConsecutive( - ['two_factor_auth_error_message', '2FA failed'], - ['two_factor_auth_error', true] - ); + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, func_get_args()); + }); $this->urlGenerator->expects($this->once()) ->method('linkToRoute') ->with('core.TwoFactorChallenge.showChallenge', [ @@ -337,7 +327,7 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token', '/url')); } - public function testSetUpProviders() { + public function testSetUpProviders(): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->once()) ->method('getUser') @@ -357,6 +347,7 @@ class TwoFactorChallengeControllerTest extends TestCase { $provider, ], 'logout_url' => 'logoutAttribute', + 'redirect_url' => null, ], 'guest' ); @@ -366,7 +357,7 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->assertEquals($expected, $response); } - public function testSetUpInvalidProvider() { + public function testSetUpInvalidProvider(): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->once()) ->method('getUser') @@ -392,7 +383,7 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->assertEquals($expected, $response); } - public function testSetUpProvider() { + public function testSetUpProvider(): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->once()) ->method('getUser') @@ -412,7 +403,7 @@ class TwoFactorChallengeControllerTest extends TestCase { ->method('getLoginSetup') ->with($user) ->willReturn($loginSetup); - $tmpl = $this->createMock(Template::class); + $tmpl = $this->createMock(ITemplate::class); $loginSetup->expects($this->once()) ->method('getBody') ->willReturn($tmpl); @@ -426,6 +417,7 @@ class TwoFactorChallengeControllerTest extends TestCase { 'provider' => $provider, 'logout_url' => 'logoutAttribute', 'template' => 'tmpl', + 'redirect_url' => null, ], 'guest' ); @@ -435,13 +427,14 @@ class TwoFactorChallengeControllerTest extends TestCase { $this->assertEquals($expected, $response); } - public function testConfirmProviderSetup() { + public function testConfirmProviderSetup(): void { $this->urlGenerator->expects($this->once()) ->method('linkToRoute') ->with( 'core.TwoFactorChallenge.showChallenge', [ 'challengeProviderId' => 'totp', + 'redirect_url' => null, ]) ->willReturn('2fa/select/page'); $expected = new RedirectResponse('2fa/select/page'); diff --git a/tests/Core/Controller/UserControllerTest.php b/tests/Core/Controller/UserControllerTest.php index b7b6e0c69f6..2473f280580 100644 --- a/tests/Core/Controller/UserControllerTest.php +++ b/tests/Core/Controller/UserControllerTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Core\Controller; @@ -48,7 +32,7 @@ class UserControllerTest extends TestCase { ); } - public function testGetDisplayNames() { + public function testGetDisplayNames(): void { $user = $this->createMock(IUser::class); $user->method('getDisplayName') ->willReturn('FooDisplay Name'); diff --git a/tests/Core/Controller/WellKnownControllerTest.php b/tests/Core/Controller/WellKnownControllerTest.php index 08af2a214ae..35606dc6384 100644 --- a/tests/Core/Controller/WellKnownControllerTest.php +++ b/tests/Core/Controller/WellKnownControllerTest.php @@ -2,25 +2,9 @@ declare(strict_types=1); -/* - * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. +/** + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Controller; @@ -56,7 +40,7 @@ class WellKnownControllerTest extends TestCase { } public function testHandleNotProcessed(): void { - $httpResponse = $this->controller->handle("nodeinfo"); + $httpResponse = $this->controller->handle('nodeinfo'); self::assertInstanceOf(JSONResponse::class, $httpResponse); self::assertArrayHasKey('X-NEXTCLOUD-WELL-KNOWN', $httpResponse->getHeaders()); @@ -71,14 +55,14 @@ class WellKnownControllerTest extends TestCase { $this->manager->expects(self::once()) ->method('process') ->with( - "nodeinfo", + 'nodeinfo', $this->request )->willReturn($response); $jsonResponse->expects(self::once()) ->method('addHeader') ->willReturnSelf(); - $httpResponse = $this->controller->handle("nodeinfo"); + $httpResponse = $this->controller->handle('nodeinfo'); self::assertInstanceOf(JSONResponse::class, $httpResponse); } diff --git a/tests/Core/Controller/WipeControllerTest.php b/tests/Core/Controller/WipeControllerTest.php index 5c06a867b79..5330eb599e6 100644 --- a/tests/Core/Controller/WipeControllerTest.php +++ b/tests/Core/Controller/WipeControllerTest.php @@ -2,25 +2,8 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Tests\Core\Controller; @@ -50,7 +33,7 @@ class WipeControllerTest extends TestCase { $this->remoteWipe); } - public function dataTest() { + public static function dataTest(): array { return [ // valid token, could perform operation, valid result [ true, true, true], @@ -64,10 +47,9 @@ class WipeControllerTest extends TestCase { * @param bool $valid * @param bool $couldPerform * @param bool $result - * - * @dataProvider dataTest */ - public function testCheckWipe(bool $valid, bool $couldPerform, bool $result) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTest')] + public function testCheckWipe(bool $valid, bool $couldPerform, bool $result): void { if (!$valid) { $this->remoteWipe->method('start') ->with('mytoken') @@ -93,10 +75,9 @@ class WipeControllerTest extends TestCase { * @param bool $valid * @param bool $couldPerform * @param bool $result - * - * @dataProvider dataTest */ - public function testWipeDone(bool $valid, bool $couldPerform, bool $result) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTest')] + public function testWipeDone(bool $valid, bool $couldPerform, bool $result): void { if (!$valid) { $this->remoteWipe->method('finish') ->with('mytoken') diff --git a/tests/Core/Data/LoginFlowV2CredentialsTest.php b/tests/Core/Data/LoginFlowV2CredentialsTest.php index c56a11594aa..ffa06f1a451 100644 --- a/tests/Core/Data/LoginFlowV2CredentialsTest.php +++ b/tests/Core/Data/LoginFlowV2CredentialsTest.php @@ -1,22 +1,8 @@ <?php + /** - * @author Konrad Abicht <hi@inspirito.de> - * - * @copyright Copyright (c) 2021, Konrad Abicht <hi@inspirito.de> - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Data; @@ -26,7 +12,7 @@ use OC\Core\Data\LoginFlowV2Credentials; use Test\TestCase; class LoginFlowV2CredentialsTest extends TestCase { - /** @var \OC\Core\Data\LoginFlowV2Credentials */ + /** @var LoginFlowV2Credentials */ private $fixture; public function setUp(): void { @@ -35,20 +21,20 @@ class LoginFlowV2CredentialsTest extends TestCase { $this->fixture = new LoginFlowV2Credentials('server', 'login', 'pass'); } - public function testImplementsJsonSerializable() { + public function testImplementsJsonSerializable(): void { $this->assertTrue($this->fixture instanceof JsonSerializable); } /** * Test getter functions. */ - public function testGetter() { + public function testGetter(): void { $this->assertEquals('server', $this->fixture->getServer()); $this->assertEquals('login', $this->fixture->getLoginName()); $this->assertEquals('pass', $this->fixture->getAppPassword()); } - public function testJsonSerialize() { + public function testJsonSerialize(): void { $this->assertEquals( [ 'server' => 'server', diff --git a/tests/Core/Middleware/TwoFactorMiddlewareTest.php b/tests/Core/Middleware/TwoFactorMiddlewareTest.php index fe1b53e3fa5..10afdd7c5e1 100644 --- a/tests/Core/Middleware/TwoFactorMiddlewareTest.php +++ b/tests/Core/Middleware/TwoFactorMiddlewareTest.php @@ -1,23 +1,9 @@ <?php /** - * @author Christoph Wurst <christoph@owncloud.com> - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Test\Core\Middleware; @@ -96,7 +82,7 @@ class TwoFactorMiddlewareTest extends TestCase { $this->controller = $this->createMock(Controller::class); } - public function testBeforeControllerNotLoggedIn() { + public function testBeforeControllerNotLoggedIn(): void { $this->userSession->expects($this->once()) ->method('isLoggedIn') ->willReturn(false); @@ -107,7 +93,7 @@ class TwoFactorMiddlewareTest extends TestCase { $this->middleware->beforeController($this->controller, 'index'); } - public function testBeforeSetupController() { + public function testBeforeSetupController(): void { $user = $this->createMock(IUser::class); $controller = $this->createMock(ALoginSetupController::class); $this->userSession->expects($this->any()) @@ -122,7 +108,7 @@ class TwoFactorMiddlewareTest extends TestCase { $this->middleware->beforeController($controller, 'create'); } - public function testBeforeControllerNoTwoFactorCheckNeeded() { + public function testBeforeControllerNoTwoFactorCheckNeeded(): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->once()) @@ -140,7 +126,7 @@ class TwoFactorMiddlewareTest extends TestCase { } - public function testBeforeControllerTwoFactorAuthRequired() { + public function testBeforeControllerTwoFactorAuthRequired(): void { $this->expectException(TwoFactorAuthRequiredException::class); $user = $this->createMock(IUser::class); @@ -164,7 +150,7 @@ class TwoFactorMiddlewareTest extends TestCase { } - public function testBeforeControllerUserAlreadyLoggedIn() { + public function testBeforeControllerUserAlreadyLoggedIn(): void { $this->expectException(UserAlreadyLoggedInException::class); $user = $this->createMock(IUser::class); @@ -193,7 +179,7 @@ class TwoFactorMiddlewareTest extends TestCase { $this->middleware->beforeController($twoFactorChallengeController, 'index'); } - public function testAfterExceptionTwoFactorAuthRequired() { + public function testAfterExceptionTwoFactorAuthRequired(): void { $ex = new TwoFactorAuthRequiredException(); $this->urlGenerator->expects($this->once()) @@ -205,7 +191,7 @@ class TwoFactorMiddlewareTest extends TestCase { $this->assertEquals($expected, $this->middleware->afterException($this->controller, 'index', $ex)); } - public function testAfterException() { + public function testAfterException(): void { $ex = new UserAlreadyLoggedInException(); $this->urlGenerator->expects($this->once()) @@ -217,7 +203,7 @@ class TwoFactorMiddlewareTest extends TestCase { $this->assertEquals($expected, $this->middleware->afterException($this->controller, 'index', $ex)); } - public function testRequires2FASetupDoneAnnotated() { + public function testRequires2FASetupDoneAnnotated(): void { $user = $this->createMock(IUser::class); $this->reflector @@ -248,23 +234,27 @@ class TwoFactorMiddlewareTest extends TestCase { $this->middleware->beforeController($twoFactorChallengeController, 'index'); } - public function dataRequires2FASetupDone() { - $provider = $this->createMock(IProvider::class); - $provider->method('getId') - ->willReturn('2FAftw'); - + public static function dataRequires2FASetupDone(): array { return [ - [[], false, false], - [[], true, true], - [[$provider], false, true], - [[$provider], true, true], + [false, false, false], + [false, true, true], + [true, false, true], + [true, true, true], ]; } - /** - * @dataProvider dataRequires2FASetupDone - */ - public function testRequires2FASetupDone(array $providers, bool $missingProviders, bool $expectEception) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataRequires2FASetupDone')] + public function testRequires2FASetupDone(bool $hasProvider, bool $missingProviders, bool $expectEception): void { + if ($hasProvider) { + $provider = $this->createMock(IProvider::class); + $provider->method('getId') + ->willReturn('2FAftw'); + $providers = [$provider]; + } else { + $providers = []; + } + + $user = $this->createMock(IUser::class); $this->reflector diff --git a/tests/Core/Service/LoginFlowV2ServiceUnitTest.php b/tests/Core/Service/LoginFlowV2ServiceUnitTest.php index 57443ca1328..5d05a1c6e0a 100644 --- a/tests/Core/Service/LoginFlowV2ServiceUnitTest.php +++ b/tests/Core/Service/LoginFlowV2ServiceUnitTest.php @@ -1,22 +1,8 @@ <?php + /** - * @author Konrad Abicht <hi@inspirito.de> - * - * @copyright Copyright (c) 2021, Konrad Abicht <hi@inspirito.de> - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Tests\Core\Data; @@ -27,8 +13,9 @@ use OC\Authentication\Token\IProvider; use OC\Authentication\Token\IToken; use OC\Core\Data\LoginFlowV2Credentials; use OC\Core\Data\LoginFlowV2Tokens; -use OC\Core\Db\LoginFlowV2Mapper; use OC\Core\Db\LoginFlowV2; +use OC\Core\Db\LoginFlowV2Mapper; +use OC\Core\Exception\LoginFlowV2ClientForbiddenException; use OC\Core\Exception\LoginFlowV2NotFoundException; use OC\Core\Service\LoginFlowV2Service; use OCP\AppFramework\Db\DoesNotExistException; @@ -44,25 +31,25 @@ use Test\TestCase; * Unit tests for \OC\Core\Service\LoginFlowV2Service */ class LoginFlowV2ServiceUnitTest extends TestCase { - /** @var \OCP\IConfig */ + /** @var IConfig */ private $config; - /** @var \OCP\Security\ICrypto */ + /** @var ICrypto */ private $crypto; /** @var LoggerInterface|MockObject */ private $logger; - /** @var \OC\Core\Db\LoginFlowV2Mapper */ + /** @var LoginFlowV2Mapper */ private $mapper; - /** @var \OCP\Security\ISecureRandom */ + /** @var ISecureRandom */ private $secureRandom; - /** @var \OC\Core\Service\LoginFlowV2Service */ + /** @var LoginFlowV2Service */ private $subjectUnderTest; - /** @var \OCP\AppFramework\Utility\ITimeFactory */ + /** @var ITimeFactory */ private $timeFactory; /** @var \OC\Authentication\Token\IProvider */ @@ -80,26 +67,13 @@ class LoginFlowV2ServiceUnitTest extends TestCase { * Code was moved to separate function to keep setUp function small and clear. */ private function setupSubjectUnderTest(): void { - $this->config = $this->getMockBuilder(IConfig::class) - ->disableOriginalConstructor()->getMock(); - - $this->crypto = $this->getMockBuilder(ICrypto::class) - ->disableOriginalConstructor()->getMock(); - - $this->mapper = $this->getMockBuilder(LoginFlowV2Mapper::class) - ->disableOriginalConstructor()->getMock(); - - $this->logger = $this->getMockBuilder(LoggerInterface::class) - ->disableOriginalConstructor()->getMock(); - - $this->tokenProvider = $this->getMockBuilder(IProvider::class) - ->disableOriginalConstructor()->getMock(); - - $this->secureRandom = $this->getMockBuilder(ISecureRandom::class) - ->disableOriginalConstructor()->getMock(); - - $this->timeFactory = $this->getMockBuilder(ITimeFactory::class) - ->disableOriginalConstructor()->getMock(); + $this->config = $this->createMock(IConfig::class); + $this->crypto = $this->createMock(ICrypto::class); + $this->mapper = $this->createMock(LoginFlowV2Mapper::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->tokenProvider = $this->createMock(IProvider::class); + $this->secureRandom = $this->createMock(ISecureRandom::class); + $this->timeFactory = $this->createMock(ITimeFactory::class); $this->subjectUnderTest = new LoginFlowV2Service( $this->mapper, @@ -141,11 +115,14 @@ class LoginFlowV2ServiceUnitTest extends TestCase { /* * Tests for poll */ - - public function testPollApptokenCouldNotBeDecrypted() { + public function testPollPrivateKeyCouldNotBeDecrypted(): void { $this->expectException(LoginFlowV2NotFoundException::class); $this->expectExceptionMessage('Apptoken could not be decrypted'); + $this->crypto->expects($this->once()) + ->method('decrypt') + ->willThrowException(new \Exception('HMAC mismatch')); + /* * Cannot be mocked, because functions like getLoginName are magic functions. * To be able to set internal properties, we have to use the real class here. @@ -163,7 +140,33 @@ class LoginFlowV2ServiceUnitTest extends TestCase { $this->subjectUnderTest->poll(''); } - public function testPollInvalidToken() { + public function testPollApptokenCouldNotBeDecrypted(): void { + $this->expectException(LoginFlowV2NotFoundException::class); + $this->expectExceptionMessage('Apptoken could not be decrypted'); + + /* + * Cannot be mocked, because functions like getLoginName are magic functions. + * To be able to set internal properties, we have to use the real class here. + */ + [$encrypted, $privateKey,] = $this->getOpenSSLEncryptedPublicAndPrivateKey('test'); + $loginFlowV2 = new LoginFlowV2(); + $loginFlowV2->setLoginName('test'); + $loginFlowV2->setServer('test'); + $loginFlowV2->setAppPassword('broken#' . $encrypted); + $loginFlowV2->setPrivateKey('encrypted(test)'); + + $this->crypto->expects($this->once()) + ->method('decrypt') + ->willReturn($privateKey); + + $this->mapper->expects($this->once()) + ->method('getByPollToken') + ->willReturn($loginFlowV2); + + $this->subjectUnderTest->poll('test'); + } + + public function testPollInvalidToken(): void { $this->expectException(LoginFlowV2NotFoundException::class); $this->expectExceptionMessage('Invalid token'); @@ -174,14 +177,14 @@ class LoginFlowV2ServiceUnitTest extends TestCase { $this->subjectUnderTest->poll(''); } - public function testPollTokenNotYetReady() { + public function testPollTokenNotYetReady(): void { $this->expectException(LoginFlowV2NotFoundException::class); $this->expectExceptionMessage('Token not yet ready'); $this->subjectUnderTest->poll(''); } - public function testPollRemoveDataFromDb() { + public function testPollRemoveDataFromDb(): void { [$encrypted, $privateKey] = $this->getOpenSSLEncryptedPublicAndPrivateKey('test_pass'); $this->crypto->expects($this->once()) @@ -223,7 +226,7 @@ class LoginFlowV2ServiceUnitTest extends TestCase { * Tests for getByLoginToken */ - public function testGetByLoginToken() { + public function testGetByLoginToken(): void { $loginFlowV2 = new LoginFlowV2(); $loginFlowV2->setLoginName('test_login'); $loginFlowV2->setServer('test_server'); @@ -241,7 +244,7 @@ class LoginFlowV2ServiceUnitTest extends TestCase { $this->assertEquals('test', $result->getAppPassword()); } - public function testGetByLoginTokenLoginTokenInvalid() { + public function testGetByLoginTokenLoginTokenInvalid(): void { $this->expectException(LoginFlowV2NotFoundException::class); $this->expectExceptionMessage('Login token invalid'); @@ -252,11 +255,62 @@ class LoginFlowV2ServiceUnitTest extends TestCase { $this->subjectUnderTest->getByLoginToken('test_token'); } + public function testGetByLoginTokenClientForbidden() { + $this->expectException(LoginFlowV2ClientForbiddenException::class); + $this->expectExceptionMessage('Client not allowed'); + + $allowedClients = [ + '/Custom Allowed Client/i' + ]; + + $this->config->expects($this->exactly(1)) + ->method('getSystemValue') + ->willReturn($this->returnCallback(function ($key) use ($allowedClients) { + // Note: \OCP\IConfig::getSystemValue returns either an array or string. + return $key == 'core.login_flow_v2.allowed_user_agents' ? $allowedClients : ''; + })); + + $loginFlowV2 = new LoginFlowV2(); + $loginFlowV2->setClientName('Rogue Curl Client/1.0'); + + $this->mapper->expects($this->once()) + ->method('getByLoginToken') + ->willReturn($loginFlowV2); + + $this->subjectUnderTest->getByLoginToken('test_token'); + } + + public function testGetByLoginTokenClientAllowed() { + $allowedClients = [ + '/Foo Allowed Client/i', + '/Custom Allowed Client/i' + ]; + + $loginFlowV2 = new LoginFlowV2(); + $loginFlowV2->setClientName('Custom Allowed Client Curl Client/1.0'); + + $this->config->expects($this->exactly(1)) + ->method('getSystemValue') + ->willReturn($this->returnCallback(function ($key) use ($allowedClients) { + // Note: \OCP\IConfig::getSystemValue returns either an array or string. + return $key == 'core.login_flow_v2.allowed_user_agents' ? $allowedClients : ''; + })); + + $this->mapper->expects($this->once()) + ->method('getByLoginToken') + ->willReturn($loginFlowV2); + + $result = $this->subjectUnderTest->getByLoginToken('test_token'); + + $this->assertTrue($result instanceof LoginFlowV2); + $this->assertEquals('Custom Allowed Client Curl Client/1.0', $result->getClientName()); + } + /* * Tests for startLoginFlow */ - public function testStartLoginFlow() { + public function testStartLoginFlow(): void { $loginFlowV2 = new LoginFlowV2(); $this->mapper->expects($this->once()) @@ -269,7 +323,7 @@ class LoginFlowV2ServiceUnitTest extends TestCase { $this->assertTrue($this->subjectUnderTest->startLoginFlow('test_token')); } - public function testStartLoginFlowDoesNotExistException() { + public function testStartLoginFlowDoesNotExistException(): void { $this->mapper->expects($this->once()) ->method('getByLoginToken') ->willThrowException(new DoesNotExistException('')); @@ -281,7 +335,7 @@ class LoginFlowV2ServiceUnitTest extends TestCase { * If an exception not of type DoesNotExistException is thrown, * it is expected that it is not being handled by startLoginFlow. */ - public function testStartLoginFlowException() { + public function testStartLoginFlowException(): void { $this->expectException(Exception::class); $this->mapper->expects($this->once()) @@ -295,7 +349,7 @@ class LoginFlowV2ServiceUnitTest extends TestCase { * Tests for flowDone */ - public function testFlowDone() { + public function testFlowDone(): void { [,, $publicKey] = $this->getOpenSSLEncryptedPublicAndPrivateKey('test_pass'); $loginFlowV2 = new LoginFlowV2(); @@ -311,7 +365,7 @@ class LoginFlowV2ServiceUnitTest extends TestCase { $this->secureRandom->expects($this->once()) ->method('generate') - ->with(72, ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS) + ->with(72, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS) ->willReturn('test_pass'); // session token @@ -355,7 +409,7 @@ class LoginFlowV2ServiceUnitTest extends TestCase { $this->assertEquals('server', $loginFlowV2->getServer()); } - public function testFlowDoneDoesNotExistException() { + public function testFlowDoneDoesNotExistException(): void { $this->mapper->expects($this->once()) ->method('getByLoginToken') ->willThrowException(new DoesNotExistException('')); @@ -369,7 +423,7 @@ class LoginFlowV2ServiceUnitTest extends TestCase { $this->assertFalse($result); } - public function testFlowDonePasswordlessTokenException() { + public function testFlowDonePasswordlessTokenException(): void { $this->tokenProvider->expects($this->once()) ->method('getToken') ->willThrowException(new InvalidTokenException('')); @@ -387,12 +441,12 @@ class LoginFlowV2ServiceUnitTest extends TestCase { * Tests for createTokens */ - public function testCreateTokens() { + public function testCreateTokens(): void { $this->config->expects($this->exactly(2)) ->method('getSystemValue') ->willReturn($this->returnCallback(function ($key) { // Note: \OCP\IConfig::getSystemValue returns either an array or string. - return 'openssl' == $key ? [] : ''; + return $key == 'openssl' ? [] : ''; })); $this->mapper->expects($this->once()) |