diff options
Diffstat (limited to 'tests')
23 files changed, 1181 insertions, 406 deletions
diff --git a/tests/Core/Command/Config/App/DeleteConfigTest.php b/tests/Core/Command/Config/App/DeleteConfigTest.php index ebbbb15e1b6..1e44c2aafe6 100644 --- a/tests/Core/Command/Config/App/DeleteConfigTest.php +++ b/tests/Core/Command/Config/App/DeleteConfigTest.php @@ -1,4 +1,6 @@ <?php + +declare(strict_types=1); /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -8,37 +10,31 @@ namespace Tests\Core\Command\Config\App; 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 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->consoleInput = $this->createMock(InputInterface::class); + $this->consoleOutput = $this->createMock(OutputInterface::class); - $this->command = new DeleteConfig($this->config); + $this->command = new DeleteConfig($this->appConfig); } - public function deleteData() { + public static function dataDelete(): array { return [ [ 'name', @@ -72,22 +68,16 @@ class DeleteConfigTest extends TestCase { } /** - * @dataProvider deleteData - * - * @param string $configName - * @param bool $configExists - * @param bool $checkIfExists - * @param int $expectedReturn - * @param string $expectedMessage + * @dataProvider dataDelete */ - public function testDelete($configName, $configExists, $checkIfExists, $expectedReturn, $expectedMessage): void { - $this->config->expects(($checkIfExists) ? $this->once() : $this->never()) - ->method('getAppKeys') + 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)) @@ -96,15 +86,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 c1a6265db40..89a75c0b527 100644 --- a/tests/Core/Command/Config/App/GetConfigTest.php +++ b/tests/Core/Command/Config/App/GetConfigTest.php @@ -1,4 +1,6 @@ <?php + +declare(strict_types=1); /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,40 +9,33 @@ namespace Tests\Core\Command\Config\App; -use OC\AppConfig; use OC\Core\Command\Config\App\GetConfig; 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 InputInterface&MockObject $consoleInput; + protected OutputInterface&MockObject $consoleOutput; + protected Command $command; protected function setUp(): void { parent::setUp(); - $config = $this->config = $this->getMockBuilder(AppConfig::class) - ->disableOriginalConstructor() - ->getMock(); - $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); - $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); + $this->appConfig = $this->createMock(IAppConfig::class); + $this->consoleInput = $this->createMock(InputInterface::class); + $this->consoleOutput = $this->createMock(OutputInterface::class); - /** @var \OCP\IAppConfig $config */ - $this->command = new GetConfig($config); + $this->command = new GetConfig($this->appConfig); } - public function getData() { + public static function dataGet(): array { return [ // String output as json ['name', 'newvalue', true, null, false, 'json', 0, json_encode('newvalue')], @@ -83,21 +78,12 @@ 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 + * @dataProvider dataGet */ - public function testGet($configName, $value, $configExists, $defaultValue, $hasDefault, $outputFormat, $expectedReturn, $expectedMessage): void { + 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()) + $this->appConfig->expects($this->once()) ->method('getDetails') ->with('app-name', $configName) ->willReturn(['value' => $value]); @@ -105,7 +91,7 @@ class GetConfigTest extends TestCase { } if (!$configExists) { - $this->config->expects($this->once()) + $this->appConfig->expects($this->once()) ->method('getDetails') ->with('app-name', $configName) ->willThrowException(new AppConfigUnknownKeyException()); @@ -117,14 +103,12 @@ class GetConfigTest extends TestCase { ['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], @@ -134,8 +118,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"; @@ -143,7 +126,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 1d599bf3234..099471228b4 100644 --- a/tests/Core/Command/Config/App/SetConfigTest.php +++ b/tests/Core/Command/Config/App/SetConfigTest.php @@ -1,4 +1,6 @@ <?php + +declare(strict_types=1); /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -11,37 +13,30 @@ use OC\AppConfig; use OC\Core\Command\Config\App\SetConfig; 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 InputInterface&MockObject $consoleInput; + protected OutputInterface&MockObject $consoleOutput; + protected Command $command; protected function setUp(): void { parent::setUp(); - $config = $this->config = $this->getMockBuilder(AppConfig::class) - ->disableOriginalConstructor() - ->getMock(); - $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); - $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); + $this->appConfig = $this->createMock(AppConfig::class); + $this->consoleInput = $this->createMock(InputInterface::class); + $this->consoleOutput = $this->createMock(OutputInterface::class); - /** @var \OCP\IAppConfig $config */ - $this->command = new SetConfig($config); + $this->command = new SetConfig($this->appConfig); } - public function setData() { + public static function dataSet(): array { return [ [ 'name', @@ -63,33 +58,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 + * @dataProvider dataSet */ - public function testSet($configName, $newValue, $configExists, $updateOnly, $updated, $expectedMessage): void { - $this->config->expects($this->any()) - ->method('hasKey') + 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->config->expects($this->any()) - ->method('getValueType') + $this->appConfig->method('getValueType') ->willThrowException(new AppConfigUnknownKeyException()); } else { - $this->config->expects($this->any()) - ->method('getValueType') + $this->appConfig->method('getValueType') ->willReturn(IAppConfig::VALUE_MIXED); } if ($updated) { - $this->config->expects($this->once()) + $this->appConfig->expects($this->once()) ->method('setValueMixed') ->with('app-name', $configName, $newValue); } @@ -100,25 +85,22 @@ class SetConfigTest extends TestCase { ['app', 'app-name'], ['name', $configName], ]); - $this->consoleInput->expects($this->any()) - ->method('getOption') + $this->consoleInput->method('getOption') ->willReturnMap([ ['value', $newValue], ['lazy', null], ['sensitive', null], ['no-interaction', true], ]); - $this->consoleInput->expects($this->any()) - ->method('hasParameterOption') + $this->consoleInput->method('hasParameterOption') ->willReturnMap([ ['--type', false, false], ['--value', false, true], ['--update-only', false, $updateOnly] ]); - $this->consoleOutput->expects($this->any()) - ->method('writeln') + $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/Service/LoginFlowV2ServiceUnitTest.php b/tests/Core/Service/LoginFlowV2ServiceUnitTest.php index 1c31efee8f7..dcc655b253c 100644 --- a/tests/Core/Service/LoginFlowV2ServiceUnitTest.php +++ b/tests/Core/Service/LoginFlowV2ServiceUnitTest.php @@ -126,11 +126,14 @@ class LoginFlowV2ServiceUnitTest extends TestCase { /* * Tests for poll */ - - public function testPollApptokenCouldNotBeDecrypted(): void { + 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. @@ -148,6 +151,32 @@ class LoginFlowV2ServiceUnitTest extends TestCase { $this->subjectUnderTest->poll(''); } + 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'); diff --git a/tests/autoload.php b/tests/autoload.php new file mode 100644 index 00000000000..05fc3852924 --- /dev/null +++ b/tests/autoload.php @@ -0,0 +1,16 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +require_once __DIR__ . '/../lib/base.php'; + +/** + * This is a file that applications can require to be able to autoload the class Test\TestCase from Nextcloud tests + */ + +\OC::$composerAutoloader->addPsr4('Test\\', OC::$SERVERROOT . '/tests/lib/', true); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 3fdc6b51fba..655b60f114b 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -12,8 +12,8 @@ if ($configDir) { } require_once __DIR__ . '/../lib/base.php'; +require_once __DIR__ . '/autoload.php'; -\OC::$composerAutoloader->addPsr4('Test\\', OC::$SERVERROOT . '/tests/lib/', true); \OC::$composerAutoloader->addPsr4('Tests\\', OC::$SERVERROOT . '/tests/', true); // load all enabled apps diff --git a/tests/data/broken-video.webm b/tests/data/broken-video.webm Binary files differnew file mode 100644 index 00000000000..0cafb9314f8 --- /dev/null +++ b/tests/data/broken-video.webm diff --git a/tests/lib/AllConfigTest.php b/tests/lib/AllConfigTest.php index e892e441ecf..3314ba46afc 100644 --- a/tests/lib/AllConfigTest.php +++ b/tests/lib/AllConfigTest.php @@ -91,6 +91,27 @@ class AllConfigTest extends \Test\TestCase { $config->deleteUserValue('userSet', 'appSet', 'keySet'); } + /** + * This test needs to stay! Emails are expected to be lowercase due to performance reasons. + * This way we can skip the expensive casing change on the database. + */ + public function testSetUserValueSettingsEmail(): void { + $selectAllSQL = 'SELECT `userid`, `appid`, `configkey`, `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ?'; + $config = $this->getConfig(); + + $config->setUserValue('userSet', 'settings', 'email', 'mixed.CASE@domain.COM'); + + $result = $this->connection->executeQuery($selectAllSQL, ['userSet'])->fetchAll(); + + $this->assertEquals(1, count($result)); + $this->assertEquals([ + 'userid' => 'userSet', + 'appid' => 'settings', + 'configkey' => 'email', + 'configvalue' => 'mixed.case@domain.com' + ], $result[0]); + } + public function testSetUserValueWithPreCondition(): void { $config = $this->getConfig(); diff --git a/tests/lib/Calendar/ManagerTest.php b/tests/lib/Calendar/ManagerTest.php index 6c01cd90811..cecebcfc4cf 100644 --- a/tests/lib/Calendar/ManagerTest.php +++ b/tests/lib/Calendar/ManagerTest.php @@ -27,8 +27,6 @@ use Psr\Log\LoggerInterface; use Sabre\HTTP\RequestInterface; use Sabre\HTTP\ResponseInterface; use Sabre\VObject\Component\VCalendar; -use Sabre\VObject\Document; -use Sabre\VObject\Reader; use Test\TestCase; /* @@ -60,6 +58,8 @@ class ManagerTest extends TestCase { private ServerFactory&MockObject $serverFactory; private VCalendar $vCalendar1a; + private VCalendar $vCalendar2a; + private VCalendar $vCalendar3a; protected function setUp(): void { parent::setUp(); @@ -90,6 +90,9 @@ class ManagerTest extends TestCase { $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']); $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']); $vEvent->add('SUMMARY', 'Test Event'); + $vEvent->add('SEQUENCE', 3); + $vEvent->add('STATUS', 'CONFIRMED'); + $vEvent->add('TRANSP', 'OPAQUE'); $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']); $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [ 'CN' => 'Attendee One', @@ -98,6 +101,45 @@ class ManagerTest extends TestCase { 'ROLE' => 'REQ-PARTICIPANT', 'RSVP' => 'TRUE' ]); + + // construct calendar with a event for reply + $this->vCalendar2a = new VCalendar(); + /** @var VEvent $vEvent */ + $vEvent = $this->vCalendar2a->add('VEVENT', []); + $vEvent->UID->setValue('dcc733bf-b2b2-41f2-a8cf-550ae4b67aff'); + $vEvent->add('DTSTART', '20210820'); + $vEvent->add('DTEND', '20220821'); + $vEvent->add('SUMMARY', 'berry basket'); + $vEvent->add('SEQUENCE', 3); + $vEvent->add('STATUS', 'CONFIRMED'); + $vEvent->add('TRANSP', 'OPAQUE'); + $vEvent->add('ORGANIZER', 'mailto:linus@stardew-tent-living.com', ['CN' => 'admin']); + $vEvent->add('ATTENDEE', 'mailto:pierre@general-store.com', [ + 'CN' => 'pierre@general-store.com', + 'CUTYPE' => 'INDIVIDUAL', + 'ROLE' => 'REQ-PARTICIPANT', + 'PARTSTAT' => 'ACCEPTED', + ]); + + // construct calendar with a event for reply + $this->vCalendar3a = new VCalendar(); + /** @var VEvent $vEvent */ + $vEvent = $this->vCalendar3a->add('VEVENT', []); + $vEvent->UID->setValue('dcc733bf-b2b2-41f2-a8cf-550ae4b67aff'); + $vEvent->add('DTSTART', '20210820'); + $vEvent->add('DTEND', '20220821'); + $vEvent->add('SUMMARY', 'berry basket'); + $vEvent->add('SEQUENCE', 3); + $vEvent->add('STATUS', 'CANCELLED'); + $vEvent->add('TRANSP', 'OPAQUE'); + $vEvent->add('ORGANIZER', 'mailto:linus@stardew-tent-living.com', ['CN' => 'admin']); + $vEvent->add('ATTENDEE', 'mailto:pierre@general-store.com', [ + 'CN' => 'pierre@general-store.com', + 'CUTYPE' => 'INDIVIDUAL', + 'ROLE' => 'REQ-PARTICIPANT', + 'PARTSTAT' => 'ACCEPTED', + ]); + } /** @@ -300,8 +342,42 @@ class ManagerTest extends TestCase { $recipient = 'attendee1@testing.com'; $calendar = $this->vCalendar1a; $calendar->add('METHOD', 'REQUEST'); - // test method + // Act $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert + $this->assertFalse($result); + } + + public function testHandleImipRequestWithInvalidData(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('error') + ->with('iMip message could not be processed because an error occurred while parsing the iMip message'); + // construct parameters + $principalUri = 'principals/user/attendee1'; + $sender = 'organizer@testing.com'; + $recipient = 'attendee1@testing.com'; + // Act + $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, 'Invalid data'); + // Assert $this->assertFalse($result); } @@ -333,8 +409,9 @@ class ManagerTest extends TestCase { $sender = 'organizer@testing.com'; $recipient = 'attendee1@testing.com'; $calendar = $this->vCalendar1a; - // test method + // Act $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } @@ -367,8 +444,9 @@ class ManagerTest extends TestCase { $recipient = 'attendee1@testing.com'; $calendar = $this->vCalendar1a; $calendar->add('METHOD', 'CANCEL'); - // test method + // Act $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } @@ -402,8 +480,9 @@ class ManagerTest extends TestCase { $calendar = $this->vCalendar1a; $calendar->add('METHOD', 'REQUEST'); $calendar->remove('VEVENT'); - // test method + // Act $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } @@ -437,8 +516,45 @@ class ManagerTest extends TestCase { $calendar = $this->vCalendar1a; $calendar->add('METHOD', 'REQUEST'); $calendar->VEVENT->remove('UID'); - // test method + // Act + $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert + $this->assertFalse($result); + } + + public function testHandleImipRequestWithNoOrganizer(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event dose not contains an organizer'); + // construct parameters + $principalUri = 'principals/user/attendee1'; + $sender = 'organizer@testing.com'; + $recipient = 'attendee1@testing.com'; + $calendar = $this->vCalendar1a; + $calendar->add('METHOD', 'REQUEST'); + $calendar->VEVENT->remove('ORGANIZER'); + // Act $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } @@ -472,8 +588,9 @@ class ManagerTest extends TestCase { $calendar = $this->vCalendar1a; $calendar->add('METHOD', 'REQUEST'); $calendar->VEVENT->remove('ATTENDEE'); - // test method + // Act $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } @@ -506,8 +623,9 @@ class ManagerTest extends TestCase { $recipient = 'attendee2@testing.com'; $calendar = $this->vCalendar1a; $calendar->add('METHOD', 'REQUEST'); - // test method + // Act $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } @@ -545,15 +663,16 @@ class ManagerTest extends TestCase { ->willReturn([$userCalendar]); // construct logger returns $this->logger->expects(self::once())->method('warning') - ->with('iMip message event could not be processed because the no corresponding event was found in any calendar'); + ->with('iMip message event could not be processed because no corresponding event was found in any calendar'); // construct parameters $principalUri = 'principals/user/attendee1'; $sender = 'organizer@testing.com'; $recipient = 'attendee1@testing.com'; $calendar = $this->vCalendar1a; $calendar->add('METHOD', 'REQUEST'); - // test method + // Act $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } @@ -599,62 +718,152 @@ class ManagerTest extends TestCase { $userCalendar->expects(self::once()) ->method('handleIMipMessage') ->with('', $calendar->serialize()); - // test method + // Act $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert $this->assertTrue($result); } - public function testHandleImipReplyWrongMethod(): void { + public function testHandleImipReplyWithNoCalendars(): void { + // construct calendar manager returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message could not be processed because user has no calendars'); + // construct parameters $principalUri = 'principals/user/linus'; $sender = 'pierre@general-store.com'; $recipient = 'linus@stardew-tent-living.com'; - $calendarData = $this->getVCalendarReply(); - $calendarData->METHOD = 'REQUEST'; - - $this->logger->expects(self::once()) - ->method('warning'); - $this->time->expects(self::never()) - ->method('getTime'); + $calendar = $this->vCalendar2a; + $calendar->add('METHOD', 'REPLY'); + // Act + $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert + $this->assertFalse($result); + } - $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize()); + public function testHandleImipReplyWithInvalidData(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('error') + ->with('iMip message could not be processed because an error occurred while parsing the iMip message'); + // construct parameters + $principalUri = 'principals/user/attendee1'; + $sender = 'organizer@testing.com'; + $recipient = 'attendee1@testing.com'; + // Act + $result = $manager->handleIMipReply($principalUri, $sender, $recipient, 'Invalid data'); + // Assert $this->assertFalse($result); } - public function testHandleImipReplyOrganizerNotRecipient(): void { + public function testHandleImipReplyWithNoMethod(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message contains an incorrect or invalid method'); + // construct parameters $principalUri = 'principals/user/linus'; - $recipient = 'pierre@general-store.com'; - $sender = 'linus@stardew-tent-living.com'; - $calendarData = $this->getVCalendarReply(); - - $this->logger->expects(self::once()) - ->method('warning'); - $this->time->expects(self::never()) - ->method('getTime'); - - $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize()); + $sender = 'pierre@general-store.com'; + $recipient = 'linus@stardew-tent-living.com'; + $calendar = $this->vCalendar2a; + // Act + $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } - public function testHandleImipReplyDateInThePast(): void { + public function testHandleImipReplyWithInvalidMethod(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message contains an incorrect or invalid method'); + // construct parameters $principalUri = 'principals/user/linus'; $sender = 'pierre@general-store.com'; $recipient = 'linus@stardew-tent-living.com'; - $calendarData = $this->getVCalendarReply(); - $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past - - $this->time->expects(self::once()) - ->method('getTime') - ->willReturn(time()); - - $this->logger->expects(self::once()) - ->method('warning'); - - $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize()); + $calendar = $this->vCalendar2a; + $calendar->add('METHOD', 'UNKNOWN'); + // Act + $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } - public function testHandleImipReplyNoCalendars(): void { - /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */ + public function testHandleImipReplyWithNoEvent(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ $manager = $this->getMockBuilder(Manager::class) ->setConstructorArgs([ $this->coordinator, @@ -665,30 +874,68 @@ class ManagerTest extends TestCase { $this->userManager, $this->serverFactory, ]) - ->setMethods([ - 'getCalendarsForPrincipal' - ]) + ->onlyMethods(['getCalendarsForPrincipal']) ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message contains no event'); + // construct parameters $principalUri = 'principals/user/linus'; $sender = 'pierre@general-store.com'; $recipient = 'linus@stardew-tent-living.com'; - $calendarData = $this->getVCalendarReply(); + $calendar = $this->vCalendar2a; + $calendar->add('METHOD', 'REPLY'); + $calendar->remove('VEVENT'); + // Act + $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert + $this->assertFalse($result); + } - $this->time->expects(self::once()) - ->method('getTime') - ->willReturn(1628374233); + public function testHandleImipReplyWithNoUid(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); $manager->expects(self::once()) ->method('getCalendarsForPrincipal') - ->willReturn([]); - $this->logger->expects(self::once()) - ->method('warning'); - - $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize()); + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event dose not contains a UID'); + // construct parameters + $principalUri = 'principals/user/linus'; + $sender = 'pierre@general-store.com'; + $recipient = 'linus@stardew-tent-living.com'; + $calendar = $this->vCalendar2a; + $calendar->add('METHOD', 'REPLY'); + $calendar->VEVENT->remove('UID'); + // Act + $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } - public function testHandleImipReplyEventNotFound(): void { - /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */ + public function testHandleImipReplyWithNoOrganizer(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ $manager = $this->getMockBuilder(Manager::class) ->setConstructorArgs([ $this->coordinator, @@ -699,31 +946,141 @@ class ManagerTest extends TestCase { $this->userManager, $this->serverFactory, ]) - ->setMethods([ - 'getCalendarsForPrincipal' + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event dose not contains an organizer'); + // construct parameters + $principalUri = 'principals/user/linus'; + $sender = 'pierre@general-store.com'; + $recipient = 'linus@stardew-tent-living.com'; + $calendar = $this->vCalendar2a; + $calendar->add('METHOD', 'REPLY'); + $calendar->VEVENT->remove('ORGANIZER'); + // Act + $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert + $this->assertFalse($result); + } + + public function testHandleImipReplyWithNoAttendee(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, ]) + ->onlyMethods(['getCalendarsForPrincipal']) ->getMock(); - $calendar = $this->createMock(ITestCalendar::class); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event dose not contains any attendees'); + // construct parameters $principalUri = 'principals/user/linus'; $sender = 'pierre@general-store.com'; $recipient = 'linus@stardew-tent-living.com'; - $calendarData = $this->getVCalendarReply(); + $calendar = $this->vCalendar2a; + $calendar->add('METHOD', 'REPLY'); + $calendar->VEVENT->remove('ATTENDEE'); + // Act + $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize()); + // Assert + $this->assertFalse($result); + } - $this->time->expects(self::once()) - ->method('getTime') - ->willReturn(1628374233); + public function testHandleImipReplyDateInThePast(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); $manager->expects(self::once()) ->method('getCalendarsForPrincipal') - ->willReturn([$calendar]); - $calendar->expects(self::once()) + ->willReturn([$userCalendar]); + // construct logger and time returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event could not be processed because the event is in the past'); + $this->time->expects(self::once()) + ->method('getTime') + ->willReturn(time()); + // construct parameters + $principalUri = 'principals/user/linus'; + $sender = 'pierre@general-store.com'; + $recipient = 'linus@stardew-tent-living.com'; + $calendarData = clone $this->vCalendar2a; + $calendarData->add('METHOD', 'REPLY'); + $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past + // Act + $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize()); + // Assert + $this->assertFalse($result); + } + + public function testHandleImipReplyEventNotFound(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + $userCalendar->expects(self::once()) ->method('search') ->willReturn([]); - $this->logger->expects(self::once()) - ->method('info'); - $calendar->expects(self::never()) - ->method('handleIMipMessage'); - + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct time returns + $this->time->expects(self::once()) + ->method('getTime') + ->willReturn(1628374233); + // construct parameters + $principalUri = 'principals/user/linus'; + $sender = 'pierre@general-store.com'; + $recipient = 'linus@stardew-tent-living.com'; + $calendarData = clone $this->vCalendar2a; + $calendarData->add('METHOD', 'REPLY'); + // construct logger return + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event could not be processed because no corresponding event was found in any calendar ' . $principalUri . 'and UID' . $calendarData->VEVENT->UID->getValue()); + // Act $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize()); + // Assert $this->assertFalse($result); } @@ -747,7 +1104,8 @@ class ManagerTest extends TestCase { $principalUri = 'principals/user/linus'; $sender = 'pierre@general-store.com'; $recipient = 'linus@stardew-tent-living.com'; - $calendarData = $this->getVCalendarReply(); + $calendarData = clone $this->vCalendar2a; + $calendarData->add('METHOD', 'REPLY'); $this->time->expects(self::once()) ->method('getTime') @@ -761,64 +1119,305 @@ class ManagerTest extends TestCase { $calendar->expects(self::once()) ->method('handleIMipMessage') ->with('testname.ics', $calendarData->serialize()); - + // Act $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize()); + // Assert $this->assertTrue($result); } - public function testHandleImipCancelWrongMethod(): void { + public function testHandleImipCancelWithNoCalendars(): void { + // construct calendar manager returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message could not be processed because user has no calendars'); + // construct parameters $principalUri = 'principals/user/pierre'; $sender = 'linus@stardew-tent-living.com'; $recipient = 'pierre@general-store.com'; $replyTo = null; - $calendarData = $this->getVCalendarCancel(); - $calendarData->METHOD = 'REQUEST'; - - $this->logger->expects(self::once()) - ->method('warning'); - $this->time->expects(self::never()) - ->method('getTime'); + $calendar = $this->vCalendar3a; + $calendar->add('METHOD', 'CANCEL'); + // Act + $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize()); + // Assert + $this->assertFalse($result); + } - $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize()); + public function testHandleImipCancelWithInvalidData(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('error') + ->with('iMip message could not be processed because an error occurred while parsing the iMip message'); + // construct parameters + $principalUri = 'principals/user/attendee1'; + $sender = 'organizer@testing.com'; + $recipient = 'attendee1@testing.com'; + $replyTo = null; + // Act + $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, 'Invalid data'); + // Assert $this->assertFalse($result); } - public function testHandleImipCancelAttendeeNotRecipient(): void { - $principalUri = '/user/admin'; + + public function testHandleImipCancelWithNoMethod(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message contains an incorrect or invalid method'); + // construct parameters + $principalUri = 'principals/user/pierre'; $sender = 'linus@stardew-tent-living.com'; - $recipient = 'leah@general-store.com'; + $recipient = 'pierre@general-store.com'; $replyTo = null; - $calendarData = $this->getVCalendarCancel(); + $calendar = $this->vCalendar3a; + // Act + $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize()); + // Assert + $this->assertFalse($result); + } - $this->logger->expects(self::once()) - ->method('warning'); - $this->time->expects(self::never()) - ->method('getTime'); + public function testHandleImipCancelWithInvalidMethod(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message contains an incorrect or invalid method'); + // construct parameters + $principalUri = 'principals/user/pierre'; + $sender = 'linus@stardew-tent-living.com'; + $recipient = 'pierre@general-store.com'; + $replyTo = null; + $calendar = $this->vCalendar3a; + $calendar->add('METHOD', 'UNKNOWN'); + // Act + $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize()); + // Assert + $this->assertFalse($result); + } - $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize()); + public function testHandleImipCancelWithNoEvent(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message contains no event'); + // construct parameters + $principalUri = 'principals/user/pierre'; + $sender = 'linus@stardew-tent-living.com'; + $recipient = 'pierre@general-store.com'; + $replyTo = null; + $calendar = $this->vCalendar3a; + $calendar->add('METHOD', 'CANCEL'); + $calendar->remove('VEVENT'); + // Act + $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } - public function testHandleImipCancelDateInThePast(): void { + public function testHandleImipCancelWithNoUid(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event dose not contains a UID'); + // construct parameters $principalUri = 'principals/user/pierre'; $sender = 'linus@stardew-tent-living.com'; $recipient = 'pierre@general-store.com'; $replyTo = null; - $calendarData = $this->getVCalendarCancel(); - $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past + $calendar = $this->vCalendar3a; + $calendar->add('METHOD', 'CANCEL'); + $calendar->VEVENT->remove('UID'); + // Act + $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize()); + // Assert + $this->assertFalse($result); + } - $this->time->expects(self::once()) - ->method('getTime') - ->willReturn(time()); - $this->logger->expects(self::once()) - ->method('warning'); + public function testHandleImipCancelWithNoOrganizer(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event dose not contains an organizer'); + // construct parameters + $principalUri = 'principals/user/pierre'; + $sender = 'linus@stardew-tent-living.com'; + $recipient = 'pierre@general-store.com'; + $replyTo = null; + $calendar = $this->vCalendar3a; + $calendar->add('METHOD', 'CANCEL'); + $calendar->VEVENT->remove('ORGANIZER'); + // Act + $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize()); + // Assert + $this->assertFalse($result); + } - $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize()); + public function testHandleImipCancelWithNoAttendee(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event dose not contains any attendees'); + // construct parameters + $principalUri = 'principals/user/pierre'; + $sender = 'pierre@general-store.com'; + $recipient = 'linus@stardew-tent-living.com'; + $replyTo = null; + $calendar = $this->vCalendar3a; + $calendar->add('METHOD', 'CANCEL'); + $calendar->VEVENT->remove('ATTENDEE'); + // Act + $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize()); + // Assert $this->assertFalse($result); } - public function testHandleImipCancelNoCalendars(): void { - /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */ + public function testHandleImipCancelAttendeeNotRecipient(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ $manager = $this->getMockBuilder(Manager::class) ->setConstructorArgs([ $this->coordinator, @@ -829,27 +1428,107 @@ class ManagerTest extends TestCase { $this->userManager, $this->serverFactory, ]) - ->setMethods([ - 'getCalendarsForPrincipal' + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event could not be processed because recipient must be an ATTENDEE of this event'); + // construct parameters + $principalUri = 'principals/user/pierre'; + $sender = 'linus@stardew-tent-living.com'; + $recipient = 'leah@general-store.com'; + $replyTo = null; + $calendarData = clone $this->vCalendar3a; + $calendarData->add('METHOD', 'CANCEL'); + // Act + $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize()); + // Assert + $this->assertFalse($result); + } + + public function testHandleImipCancelDateInThePast(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, ]) + ->onlyMethods(['getCalendarsForPrincipal']) ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct logger and time returns + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event could not be processed because the event is in the past'); + $this->time->expects(self::once()) + ->method('getTime') + ->willReturn(time()); + // construct parameters $principalUri = 'principals/user/pierre'; $sender = 'linus@stardew-tent-living.com'; $recipient = 'pierre@general-store.com'; $replyTo = null; - $calendarData = $this->getVCalendarCancel(); + $calendarData = clone $this->vCalendar3a; + $calendarData->add('METHOD', 'CANCEL'); + $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past + // Act + $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize()); + // Assert + $this->assertFalse($result); + } + public function testHandleImipCancelEventNotFound(): void { + // construct mock user calendar + $userCalendar = $this->createMock(ITestCalendar::class); + $userCalendar->expects(self::once()) + ->method('search') + ->willReturn([]); + // construct mock calendar manager and returns + /** @var Manager&MockObject $manager */ + $manager = $this->getMockBuilder(Manager::class) + ->setConstructorArgs([ + $this->coordinator, + $this->container, + $this->logger, + $this->time, + $this->secureRandom, + $this->userManager, + $this->serverFactory, + ]) + ->onlyMethods(['getCalendarsForPrincipal']) + ->getMock(); + $manager->expects(self::once()) + ->method('getCalendarsForPrincipal') + ->willReturn([$userCalendar]); + // construct time returns $this->time->expects(self::once()) ->method('getTime') ->willReturn(1628374233); - $manager->expects(self::once()) - ->method('getCalendarsForPrincipal') - ->with($principalUri) - ->willReturn([]); - $this->logger->expects(self::once()) - ->method('warning'); - + // construct parameters + $principalUri = 'principals/user/pierre'; + $sender = 'linus@stardew-tent-living.com'; + $recipient = 'pierre@general-store.com'; + $replyTo = null; + $calendarData = clone $this->vCalendar3a; + $calendarData->add('METHOD', 'CANCEL'); + // construct logger return + $this->logger->expects(self::once())->method('warning') + ->with('iMip message event could not be processed because no corresponding event was found in any calendar ' . $principalUri . 'and UID' . $calendarData->VEVENT->UID->getValue()); + // Act $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize()); + // Assert $this->assertFalse($result); } @@ -869,12 +1548,14 @@ class ManagerTest extends TestCase { 'getCalendarsForPrincipal' ]) ->getMock(); + $principalUri = 'principals/user/pierre'; - $sender = 'clint@stardew-blacksmiths.com'; + $sender = 'clint@stardew-tent-living.com'; $recipient = 'pierre@general-store.com'; $replyTo = 'linus@stardew-tent-living.com'; $calendar = $this->createMock(ITestCalendar::class); - $calendarData = $this->getVCalendarCancel(); + $calendarData = clone $this->vCalendar3a; + $calendarData->add('METHOD', 'CANCEL'); $this->time->expects(self::once()) ->method('getTime') @@ -889,7 +1570,9 @@ class ManagerTest extends TestCase { $calendar->expects(self::once()) ->method('handleIMipMessage') ->with('testname.ics', $calendarData->serialize()); + // Act $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize()); + // Assert $this->assertTrue($result); } @@ -914,7 +1597,8 @@ class ManagerTest extends TestCase { $recipient = 'pierre@general-store.com'; $replyTo = null; $calendar = $this->createMock(ITestCalendar::class); - $calendarData = $this->getVCalendarCancel(); + $calendarData = clone $this->vCalendar3a; + $calendarData->add('METHOD', 'CANCEL'); $this->time->expects(self::once()) ->method('getTime') @@ -929,68 +1613,12 @@ class ManagerTest extends TestCase { $calendar->expects(self::once()) ->method('handleIMipMessage') ->with('testname.ics', $calendarData->serialize()); + // Act $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize()); + // Assert $this->assertTrue($result); } - private function getVCalendarReply(): Document { - $data = <<<EOF -BEGIN:VCALENDAR -PRODID:-//Nextcloud/Nextcloud CalDAV Server//EN -VERSION:2.0 -CALSCALE:GREGORIAN -METHOD:REPLY -BEGIN:VEVENT -DTSTART;VALUE=DATE:20210820 -DTEND;VALUE=DATE:20220821 -DTSTAMP:20210812T100040Z -ORGANIZER;CN=admin:mailto:linus@stardew-tent-living.com -UID:dcc733bf-b2b2-41f2-a8cf-550ae4b67aff -ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=pierr - e@general-store.com;X-NUM-GUESTS=0:mailto:pierre@general-store.com -CREATED:20220812T100021Z -DESCRIPTION: -LAST-MODIFIED:20220812T100040Z -LOCATION: -SEQUENCE:3 -STATUS:CONFIRMED -SUMMARY:berry basket -TRANSP:OPAQUE -END:VEVENT -END:VCALENDAR -EOF; - return Reader::read($data); - } - - private function getVCalendarCancel(): Document { - $data = <<<EOF -BEGIN:VCALENDAR -PRODID:-//Nextcloud/Nextcloud CalDAV Server//EN -VERSION:2.0 -CALSCALE:GREGORIAN -METHOD:CANCEL -BEGIN:VEVENT -DTSTART;VALUE=DATE:20210820 -DTEND;VALUE=DATE:20220821 -DTSTAMP:20210812T100040Z -ORGANIZER;CN=admin:mailto:linus@stardew-tent-living.com -UID:dcc733bf-b2b2-41f2-a8cf-550ae4b67aff -ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=pierr - e@general-store.com;X-NUM-GUESTS=0:mailto:pierre@general-store.com -CREATED:20220812T100021Z -DESCRIPTION: -LAST-MODIFIED:20220812T100040Z -LOCATION: -SEQUENCE:3 -STATUS:CANCELLED -SUMMARY:berry basket -TRANSP:OPAQUE -END:VEVENT -END:VCALENDAR -EOF; - return Reader::read($data); - } - private function getFreeBusyResponse(): string { return <<<EOF <?xml version="1.0" encoding="utf-8"?> diff --git a/tests/lib/Comments/ManagerTest.php b/tests/lib/Comments/ManagerTest.php index 15961b029f5..450aab16e79 100644 --- a/tests/lib/Comments/ManagerTest.php +++ b/tests/lib/Comments/ManagerTest.php @@ -1099,6 +1099,7 @@ class ManagerTest extends TestCase { * @return IComment[] */ private function proccessComments(array $data): array { + $this->connection->beginTransaction(); /** @var IComment[] */ $comments = []; foreach ($data as $comment) { @@ -1114,6 +1115,7 @@ class ManagerTest extends TestCase { $comment = $this->testSave($message, $actorId, $verb, $parentId, $id); $comments[$comment->getMessage() . '#' . $comment->getActorId()] = $comment; } + $this->connection->commit(); return $comments; } diff --git a/tests/lib/Config/UserConfigTest.php b/tests/lib/Config/UserConfigTest.php index f9a9b5c5272..93483a9b71a 100644 --- a/tests/lib/Config/UserConfigTest.php +++ b/tests/lib/Config/UserConfigTest.php @@ -1249,6 +1249,19 @@ class UserConfigTest extends TestCase { } } + /** + * This test needs to stay! Emails are expected to be lowercase due to performance reasons. + * This way we can skip the expensive casing change on the database. + */ + public function testSetValueMixedWithSettingsEmail(): void { + $userConfig = $this->generateUserConfig(); + + $edited = $userConfig->setValueMixed('user1', 'settings', 'email', 'mixed.CASE@Nextcloud.com'); + $this->assertTrue($edited); + + $actual = $userConfig->getValueMixed('user1', 'settings', 'email'); + $this->assertEquals('mixed.case@nextcloud.com', $actual); + } public function providerSetValueString(): array { return [ diff --git a/tests/lib/Files/Cache/Wrapper/CacheJailTest.php b/tests/lib/Files/Cache/Wrapper/CacheJailTest.php index aed13c41ac0..57024e2eb79 100644 --- a/tests/lib/Files/Cache/Wrapper/CacheJailTest.php +++ b/tests/lib/Files/Cache/Wrapper/CacheJailTest.php @@ -8,6 +8,7 @@ namespace Test\Files\Cache\Wrapper; use OC\Files\Cache\Wrapper\CacheJail; +use OC\Files\Cache\Wrapper\CacheWrapper; use OC\Files\Search\SearchComparison; use OC\Files\Search\SearchQuery; use OC\Files\Storage\Wrapper\Jail; @@ -252,4 +253,14 @@ class CacheJailTest extends CacheTest { $storage->getWatcher()->update('bar', ['mimetype' => 'text/plain']); $this->assertTrue($this->cache->inCache('bar')); } + + public function testUnJailedRoot(): void { + $jail1 = new CacheJail($this->sourceCache, 'foo'); + $jail2 = new CacheJail($jail1, 'bar'); + $this->assertEquals('foo/bar', $jail2->getGetUnjailedRoot()); + + $middleWrapper = new CacheWrapper($jail1); + $jail3 = new CacheJail($middleWrapper, 'bar'); + $this->assertEquals('foo/bar', $jail3->getGetUnjailedRoot()); + } } diff --git a/tests/lib/Files/Config/UserMountCacheTest.php b/tests/lib/Files/Config/UserMountCacheTest.php index 1efc56c1908..d61fcf636b7 100644 --- a/tests/lib/Files/Config/UserMountCacheTest.php +++ b/tests/lib/Files/Config/UserMountCacheTest.php @@ -9,6 +9,7 @@ namespace Test\Files\Config; use OC\DB\Exceptions\DbalException; use OC\DB\QueryBuilder\Literal; +use OC\Files\Config\UserMountCache; use OC\Files\Mount\MountPoint; use OC\Files\Storage\Storage; use OC\User\Manager; @@ -16,6 +17,9 @@ use OCP\Cache\CappedMemoryCache; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Diagnostics\IEventLogger; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Config\Event\UserMountAddedEvent; +use OCP\Files\Config\Event\UserMountRemovedEvent; +use OCP\Files\Config\Event\UserMountUpdatedEvent; use OCP\Files\Config\ICachedMountInfo; use OCP\ICacheFactory; use OCP\IConfig; @@ -29,28 +33,19 @@ use Test\Util\User\Dummy; * @group DB */ class UserMountCacheTest extends TestCase { - /** - * @var IDBConnection - */ - private $connection; - - /** - * @var IUserManager - */ - private $userManager; - - /** - * @var \OC\Files\Config\UserMountCache - */ - private $cache; - - private $fileIds = []; + private IDBConnection $connection; + private IUserManager $userManager; + private IEventDispatcher $eventDispatcher; + private UserMountCache $cache; + private array $fileIds = []; protected function setUp(): void { parent::setUp(); $this->fileIds = []; + $this->connection = \OC::$server->getDatabaseConnection(); + $config = $this->getMockBuilder(IConfig::class) ->disableOriginalConstructor() ->getMock(); @@ -62,13 +57,22 @@ class UserMountCacheTest extends TestCase { ->expects($this->any()) ->method('getAppValue') ->willReturnArgument(2); + $this->userManager = new Manager($config, $this->createMock(ICacheFactory::class), $this->createMock(IEventDispatcher::class), $this->createMock(LoggerInterface::class)); $userBackend = new Dummy(); $userBackend->createUser('u1', ''); $userBackend->createUser('u2', ''); $userBackend->createUser('u3', ''); $this->userManager->registerBackend($userBackend); - $this->cache = new \OC\Files\Config\UserMountCache($this->connection, $this->userManager, $this->createMock(LoggerInterface::class), $this->createMock(IEventLogger::class)); + + $this->eventDispatcher = $this->createMock(IEventDispatcher::class); + + $this->cache = new UserMountCache($this->connection, + $this->userManager, + $this->createMock(LoggerInterface::class), + $this->createMock(IEventLogger::class), + $this->eventDispatcher, + ); } protected function tearDown(): void { @@ -126,6 +130,11 @@ class UserMountCacheTest extends TestCase { } public function testNewMounts(): void { + $this->eventDispatcher + ->expects($this->once()) + ->method('dispatchTyped') + ->with($this->callback(fn (UserMountAddedEvent $event) => $event->mountPoint->getMountPoint() === '/asd/')); + $user = $this->userManager->get('u1'); [$storage] = $this->getStorage(10); @@ -146,6 +155,11 @@ class UserMountCacheTest extends TestCase { } public function testSameMounts(): void { + $this->eventDispatcher + ->expects($this->once()) + ->method('dispatchTyped') + ->with($this->callback(fn (UserMountAddedEvent $event) => $event->mountPoint->getMountPoint() === '/asd/')); + $user = $this->userManager->get('u1'); [$storage] = $this->getStorage(10); @@ -170,6 +184,18 @@ class UserMountCacheTest extends TestCase { } public function testRemoveMounts(): void { + $operation = 0; + $this->eventDispatcher + ->expects($this->exactly(2)) + ->method('dispatchTyped') + ->with($this->callback(function (UserMountAddedEvent|UserMountRemovedEvent $event) use (&$operation) { + return match(++$operation) { + 1 => $event instanceof UserMountAddedEvent && $event->mountPoint->getMountPoint() === '/asd/', + 2 => $event instanceof UserMountRemovedEvent && $event->mountPoint->getMountPoint() === '/asd/', + default => false, + }; + })); + $user = $this->userManager->get('u1'); [$storage] = $this->getStorage(10); @@ -189,6 +215,19 @@ class UserMountCacheTest extends TestCase { } public function testChangeMounts(): void { + $operation = 0; + $this->eventDispatcher + ->expects($this->exactly(3)) + ->method('dispatchTyped') + ->with($this->callback(function (UserMountAddedEvent|UserMountRemovedEvent $event) use (&$operation) { + return match(++$operation) { + 1 => $event instanceof UserMountAddedEvent && $event->mountPoint->getMountPoint() === '/bar/', + 2 => $event instanceof UserMountAddedEvent && $event->mountPoint->getMountPoint() === '/foo/', + 3 => $event instanceof UserMountRemovedEvent && $event->mountPoint->getMountPoint() === '/bar/', + default => false, + }; + })); + $user = $this->userManager->get('u1'); [$storage] = $this->getStorage(10); @@ -212,6 +251,18 @@ class UserMountCacheTest extends TestCase { } public function testChangeMountId(): void { + $operation = 0; + $this->eventDispatcher + ->expects($this->exactly(2)) + ->method('dispatchTyped') + ->with($this->callback(function (UserMountAddedEvent|UserMountUpdatedEvent $event) use (&$operation) { + return match(++$operation) { + 1 => $event instanceof UserMountAddedEvent && $event->mountPoint->getMountPoint() === '/foo/', + 2 => $event instanceof UserMountUpdatedEvent && $event->oldMountPoint->getMountId() === null && $event->newMountPoint->getMountId() === 1, + default => false, + }; + })); + $user = $this->userManager->get('u1'); [$storage] = $this->getStorage(10); diff --git a/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php b/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php index 3dbdc3afc27..508f328fae2 100644 --- a/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php +++ b/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php @@ -262,4 +262,17 @@ class ObjectStoreStorageTest extends Storage { $this->assertTrue($cache->inCache('new.txt')); $this->assertEquals(\OCP\Constants::PERMISSION_ALL, $instance->getPermissions('new.txt')); } + + public function testCopyFolderSize(): void { + $cache = $this->instance->getCache(); + + $this->instance->mkdir('source'); + $this->instance->file_put_contents('source/test.txt', 'foo'); + $this->instance->getUpdater()->update('source/test.txt'); + $this->assertEquals(3, $cache->get('source')->getSize()); + + $this->assertTrue($this->instance->copy('source', 'target')); + + $this->assertEquals(3, $cache->get('target')->getSize()); + } } diff --git a/tests/lib/NavigationManagerTest.php b/tests/lib/NavigationManagerTest.php index d9db928e8a1..bcd63bb3af9 100644 --- a/tests/lib/NavigationManagerTest.php +++ b/tests/lib/NavigationManagerTest.php @@ -704,30 +704,64 @@ class NavigationManagerTest extends TestCase { true, 'settings', ], + // closure navigation entries are also resolved + [ + 'closure2', + '', + '', + true, + 'closure2', + ], + [ + '', + 'closure2', + '', + true, + 'closure2', + ], + [ + '', + '', + '{"closure2":{"order":1,"app":"closure2","href":"/closure2"}}', + true, + 'closure2', + ], ]; } /** * @dataProvider provideDefaultEntries */ - public function testGetDefaultEntryIdForUser($defaultApps, $userDefaultApps, $userApporder, $withFallbacks, $expectedApp): void { + public function testGetDefaultEntryIdForUser(string $defaultApps, string $userDefaultApps, string $userApporder, bool $withFallbacks, string $expectedApp): void { $this->navigationManager->add([ 'id' => 'files', ]); $this->navigationManager->add([ 'id' => 'settings', ]); + $this->navigationManager->add(static function (): array { + return [ + 'id' => 'closure1', + 'href' => '/closure1', + ]; + }); + $this->navigationManager->add(static function (): array { + return [ + 'id' => 'closure2', + 'href' => '/closure2', + ]; + }); $this->appManager->method('getInstalledApps')->willReturn([]); $user = $this->createMock(IUser::class); $user->method('getUID')->willReturn('user1'); - $this->userSession->expects($this->once()) + $this->userSession->expects($this->atLeastOnce()) ->method('getUser') ->willReturn($user); - $this->config->expects($this->once()) + $this->config->expects($this->atLeastOnce()) ->method('getSystemValueString') ->with('defaultapp', $this->anything()) ->willReturn($defaultApps); diff --git a/tests/lib/Preview/BackgroundCleanupJobTest.php b/tests/lib/Preview/BackgroundCleanupJobTest.php index 945366cde9f..cecb4a7a212 100644 --- a/tests/lib/Preview/BackgroundCleanupJobTest.php +++ b/tests/lib/Preview/BackgroundCleanupJobTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-only @@ -9,12 +10,15 @@ namespace Test\Preview; use OC\Preview\BackgroundCleanupJob; use OC\Preview\Storage\Root; use OC\PreviewManager; +use OCP\App\IAppManager; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Files\File; use OCP\Files\IMimeTypeLoader; use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; use OCP\IDBConnection; +use OCP\IPreview; +use OCP\Server; use Test\Traits\MountProviderTrait; use Test\Traits\UserTrait; @@ -28,25 +32,12 @@ use Test\Traits\UserTrait; class BackgroundCleanupJobTest extends \Test\TestCase { use MountProviderTrait; use UserTrait; - - /** @var string */ - private $userId; - - /** @var bool */ - private $trashEnabled; - - /** @var IDBConnection */ - private $connection; - - /** @var PreviewManager */ - private $previewManager; - - /** @var IRootFolder */ - private $rootFolder; - - /** @var IMimeTypeLoader */ - private $mimeTypeLoader; - + private string $userId; + private bool $trashEnabled; + private IDBConnection $connection; + private PreviewManager $previewManager; + private IRootFolder $rootFolder; + private IMimeTypeLoader $mimeTypeLoader; private ITimeFactory $timeFactory; protected function setUp(): void { @@ -62,20 +53,20 @@ class BackgroundCleanupJobTest extends \Test\TestCase { $this->logout(); $this->loginAsUser($this->userId); - $appManager = \OC::$server->getAppManager(); + $appManager = Server::get(IAppManager::class); $this->trashEnabled = $appManager->isEnabledForUser('files_trashbin', $user); $appManager->disableApp('files_trashbin'); - $this->connection = \OC::$server->getDatabaseConnection(); - $this->previewManager = \OC::$server->getPreviewManager(); - $this->rootFolder = \OC::$server->get(IRootFolder::class); - $this->mimeTypeLoader = \OC::$server->getMimeTypeLoader(); - $this->timeFactory = \OCP\Server::get(ITimeFactory::class); + $this->connection = Server::get(IDBConnection::class); + $this->previewManager = Server::get(IPreview::class); + $this->rootFolder = Server::get(IRootFolder::class); + $this->mimeTypeLoader = Server::get(IMimeTypeLoader::class); + $this->timeFactory = Server::get(ITimeFactory::class); } protected function tearDown(): void { if ($this->trashEnabled) { - $appManager = \OC::$server->getAppManager(); + $appManager = Server::get(IAppManager::class); $appManager->enableApp('files_trashbin'); } diff --git a/tests/lib/Preview/GeneratorTest.php b/tests/lib/Preview/GeneratorTest.php index 8a08d741909..607127a6495 100644 --- a/tests/lib/Preview/GeneratorTest.php +++ b/tests/lib/Preview/GeneratorTest.php @@ -22,25 +22,25 @@ use OCP\Preview\IProviderV2; use Psr\Log\LoggerInterface; class GeneratorTest extends \Test\TestCase { - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ + /** @var IConfig&\PHPUnit\Framework\MockObject\MockObject */ private $config; - /** @var IPreview|\PHPUnit\Framework\MockObject\MockObject */ + /** @var IPreview&\PHPUnit\Framework\MockObject\MockObject */ private $previewManager; - /** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */ + /** @var IAppData&\PHPUnit\Framework\MockObject\MockObject */ private $appData; - /** @var GeneratorHelper|\PHPUnit\Framework\MockObject\MockObject */ + /** @var GeneratorHelper&\PHPUnit\Framework\MockObject\MockObject */ private $helper; - /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */ + /** @var IEventDispatcher&\PHPUnit\Framework\MockObject\MockObject */ private $eventDispatcher; /** @var Generator */ private $generator; - private LoggerInterface|\PHPUnit\Framework\MockObject\MockObject $logger; + private LoggerInterface&\PHPUnit\Framework\MockObject\MockObject $logger; protected function setUp(): void { parent::setUp(); @@ -196,18 +196,10 @@ class GeneratorTest extends \Test\TestCase { $previewFolder->method('getDirectoryListing') ->willReturn([]); $previewFolder->method('newFile') - ->willReturnCallback(function ($filename) use ($maxPreview, $previewFile) { - if ($filename === '2048-2048-max.png') { - return $maxPreview; - } elseif ($filename === '256-256.png') { - return $previewFile; - } - $this->fail('Unexpected file'); - }); - - $maxPreview->expects($this->once()) - ->method('putContent') - ->with($this->equalTo('my data')); + ->willReturnMap([ + ['2048-2048-max.png', 'my data', $maxPreview], + ['256-256.png', 'my resized data', $previewFile], + ]); $previewFolder->method('getFile') ->with($this->equalTo('256-256.png')) @@ -218,10 +210,6 @@ class GeneratorTest extends \Test\TestCase { ->with($this->equalTo($maxPreview)) ->willReturn($image); - $previewFile->expects($this->once()) - ->method('putContent') - ->with('my resized data'); - $this->eventDispatcher->expects($this->once()) ->method('dispatchTyped') ->with(new BeforePreviewFetchedEvent($file, 100, 100, false, IPreview::MODE_FILL, null)); diff --git a/tests/lib/Preview/MovieBrokenStuckFfmpegTest.php b/tests/lib/Preview/MovieBrokenStuckFfmpegTest.php new file mode 100644 index 00000000000..e66d5e64649 --- /dev/null +++ b/tests/lib/Preview/MovieBrokenStuckFfmpegTest.php @@ -0,0 +1,20 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace Test\Preview; + +/** + * Class MovieTest + * + * @group DB + * + * @package Test\Preview + */ +class MovieBrokenStuckFfmpegTest extends MovieTest { + protected string $fileName = 'broken-video.webm'; +} diff --git a/tests/lib/Preview/MovieTest.php b/tests/lib/Preview/MovieTest.php index d41b242945b..b63fef8b48d 100644 --- a/tests/lib/Preview/MovieTest.php +++ b/tests/lib/Preview/MovieTest.php @@ -15,6 +15,10 @@ namespace Test\Preview; * @package Test\Preview */ class MovieTest extends Provider { + protected string $fileName = 'testimage.mp4'; + protected int $width = 560; + protected int $height = 320; + protected function setUp(): void { $avconvBinary = \OC_Helper::findBinaryPath('avconv'); $ffmpegBinary = ($avconvBinary) ? null : \OC_Helper::findBinaryPath('ffmpeg'); @@ -25,10 +29,7 @@ class MovieTest extends Provider { \OC\Preview\Movie::$avconvBinary = $avconvBinary; \OC\Preview\Movie::$ffmpegBinary = $ffmpegBinary; - $fileName = 'testimage.mp4'; - $this->imgPath = $this->prepareTestFile($fileName, \OC::$SERVERROOT . '/tests/data/' . $fileName); - $this->width = 560; - $this->height = 320; + $this->imgPath = $this->prepareTestFile($this->fileName, \OC::$SERVERROOT . '/tests/data/' . $this->fileName); $this->provider = new \OC\Preview\Movie; } else { $this->markTestSkipped('No Movie provider present'); diff --git a/tests/lib/Preview/Provider.php b/tests/lib/Preview/Provider.php index 41a2a4ca3c4..a7f55151354 100644 --- a/tests/lib/Preview/Provider.php +++ b/tests/lib/Preview/Provider.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -9,33 +10,25 @@ namespace Test\Preview; use OC\Files\Node\File; use OCP\Files\IRootFolder; +use OCP\IUserManager; abstract class Provider extends \Test\TestCase { - /** @var string */ - protected $imgPath; - /** @var int */ - protected $width; - /** @var int */ - protected $height; - /** @var \OC\Preview\Provider */ + protected string $imgPath; + protected int $width; + protected int $height; + /** @var \OC\Preview\Provider|mixed $provider */ protected $provider; - /** @var int */ - protected $maxWidth = 1024; - /** @var int */ - protected $maxHeight = 1024; - /** @var bool */ - protected $scalingUp = false; - /** @var int */ - protected $userId; - /** @var \OC\Files\View */ - protected $rootView; - /** @var \OC\Files\Storage\Storage */ - protected $storage; + protected int $maxWidth = 1024; + protected int $maxHeight = 1024; + protected bool $scalingUp = false; + protected string $userId; + protected \OC\Files\View $rootView; + protected \OC\Files\Storage\Storage $storage; protected function setUp(): void { parent::setUp(); - $userManager = \OC::$server->getUserManager(); + $userManager = \OCP\Server::get(IUserManager::class); $userManager->clearBackends(); $backend = new \Test\Util\User\Dummy(); $userManager->registerBackend($backend); diff --git a/tests/lib/Security/RateLimiting/LimiterTest.php b/tests/lib/Security/RateLimiting/LimiterTest.php index 92600e22de8..6f430e85576 100644 --- a/tests/lib/Security/RateLimiting/LimiterTest.php +++ b/tests/lib/Security/RateLimiting/LimiterTest.php @@ -12,21 +12,26 @@ namespace Test\Security\RateLimiting; use OC\Security\RateLimiting\Backend\IBackend; use OC\Security\RateLimiting\Limiter; use OCP\IUser; +use OCP\Security\RateLimiting\ILimiter; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; class LimiterTest extends TestCase { - /** @var IBackend|\PHPUnit\Framework\MockObject\MockObject */ - private $backend; - /** @var Limiter */ - private $limiter; + + private IBackend&MockObject $backend; + private ILimiter $limiter; + private LoggerInterface $logger; protected function setUp(): void { parent::setUp(); $this->backend = $this->createMock(IBackend::class); + $this->logger = $this->createMock(LoggerInterface::class); $this->limiter = new Limiter( - $this->backend + $this->backend, + $this->logger, ); } @@ -43,6 +48,8 @@ class LimiterTest extends TestCase { '4664f0d9c88dcb7552be47b37bb52ce35977b2e60e1ac13757cf625f31f87050a41f3da064887fa87d49fd042e4c8eb20de8f10464877d3959677ab011b73a47' ) ->willReturn(101); + $this->logger->expects($this->once()) + ->method('info'); $this->limiter->registerAnonRequest('MyIdentifier', 100, 100, '127.0.0.1'); } @@ -64,6 +71,8 @@ class LimiterTest extends TestCase { '4664f0d9c88dcb7552be47b37bb52ce35977b2e60e1ac13757cf625f31f87050a41f3da064887fa87d49fd042e4c8eb20de8f10464877d3959677ab011b73a47', 100 ); + $this->logger->expects($this->never()) + ->method('info'); $this->limiter->registerAnonRequest('MyIdentifier', 100, 100, '127.0.0.1'); } @@ -87,6 +96,8 @@ class LimiterTest extends TestCase { 'ddb2ec50fa973fd49ecf3d816f677c8095143e944ad10485f30fb3dac85c13a346dace4dae2d0a15af91867320957bfd38a43d9eefbb74fe6919e15119b6d805' ) ->willReturn(101); + $this->logger->expects($this->once()) + ->method('info'); $this->limiter->registerUserRequest('MyIdentifier', 100, 100, $user); } @@ -115,6 +126,8 @@ class LimiterTest extends TestCase { 'ddb2ec50fa973fd49ecf3d816f677c8095143e944ad10485f30fb3dac85c13a346dace4dae2d0a15af91867320957bfd38a43d9eefbb74fe6919e15119b6d805', 100 ); + $this->logger->expects($this->never()) + ->method('info'); $this->limiter->registerUserRequest('MyIdentifier', 100, 100, $user); } diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php index 03731a90754..c4688f445d7 100644 --- a/tests/lib/Share20/ManagerTest.php +++ b/tests/lib/Share20/ManagerTest.php @@ -55,6 +55,7 @@ use OCP\Share\IManager; use OCP\Share\IProviderFactory; use OCP\Share\IShare; use OCP\Share\IShareProvider; +use OCP\Share\IShareProviderSupportsAllSharesInFolder; use PHPUnit\Framework\MockObject\MockBuilder; use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; @@ -4552,7 +4553,7 @@ class ManagerTest extends \Test\TestCase { $manager = $this->createManager($factory); $factory->setProvider($this->defaultProvider); - $extraProvider = $this->createMock(IShareProvider::class); + $extraProvider = $this->createMock(IShareProviderSupportsAllSharesInFolder::class); $factory->setSecondProvider($extraProvider); $share1 = $this->createMock(IShare::class); @@ -4560,28 +4561,20 @@ class ManagerTest extends \Test\TestCase { $mount = $this->createMock(IShareOwnerlessMount::class); - $file = $this->createMock(File::class); - $file - ->method('getId') - ->willReturn(1); - $folder = $this->createMock(Folder::class); $folder ->method('getMountPoint') ->willReturn($mount); - $folder - ->method('getDirectoryListing') - ->willReturn([$file]); $this->defaultProvider - ->method('getSharesByPath') - ->with($file) - ->willReturn([$share1]); + ->method('getAllSharesInFolder') + ->with($folder) + ->willReturn([1 => [$share1]]); $extraProvider - ->method('getSharesByPath') - ->with($file) - ->willReturn([$share2]); + ->method('getAllSharesInFolder') + ->with($folder) + ->willReturn([1 => [$share2]]); $this->assertSame([ 1 => [$share1, $share2], diff --git a/tests/lib/TaskProcessing/TaskProcessingTest.php b/tests/lib/TaskProcessing/TaskProcessingTest.php index 73f67b07266..d463a5e4c61 100644 --- a/tests/lib/TaskProcessing/TaskProcessingTest.php +++ b/tests/lib/TaskProcessing/TaskProcessingTest.php @@ -27,6 +27,7 @@ use OCP\IDBConnection; use OCP\IServerContainer; use OCP\IUser; use OCP\IUserManager; +use OCP\IUserSession; use OCP\TaskProcessing\EShapeType; use OCP\TaskProcessing\Events\GetTaskProcessingProvidersEvent; use OCP\TaskProcessing\Events\TaskFailedEvent; @@ -608,6 +609,8 @@ class TaskProcessingTest extends \Test\TestCase { $this->userMountCache, \OC::$server->get(IClientService::class), \OC::$server->get(IAppManager::class), + $userManager, + \OC::$server->get(IUserSession::class), \OC::$server->get(ICacheFactory::class), ); } @@ -1258,6 +1261,8 @@ class TaskProcessingTest extends \Test\TestCase { $this->userMountCache, \OC::$server->get(IClientService::class), \OC::$server->get(IAppManager::class), + \OC::$server->get(IUserManager::class), + \OC::$server->get(IUserSession::class), \OC::$server->get(ICacheFactory::class), ); } |