diff options
Diffstat (limited to 'apps/dav/tests/unit/BackgroundJob')
10 files changed, 711 insertions, 646 deletions
diff --git a/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php b/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php index 6233980edbb..b2199e3e657 100644 --- a/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php +++ b/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php @@ -3,48 +3,23 @@ declare(strict_types=1); /** - * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Georg Ehrke <oc.list@georgehrke.com> - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @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 OCA\DAV\Tests\unit\BackgroundJob; use OCA\DAV\BackgroundJob\CleanupInvitationTokenJob; use OCP\AppFramework\Utility\ITimeFactory; +use OCP\DB\QueryBuilder\IExpressionBuilder; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class CleanupInvitationTokenJobTest extends TestCase { - - /** @var IDBConnection | \PHPUnit\Framework\MockObject\MockObject */ - private $dbConnection; - - /** @var ITimeFactory | \PHPUnit\Framework\MockObject\MockObject */ - private $timeFactory; - - /** @var \OCA\DAV\BackgroundJob\GenerateBirthdayCalendarBackgroundJob */ - private $backgroundJob; + private IDBConnection&MockObject $dbConnection; + private ITimeFactory&MockObject $timeFactory; + private CleanupInvitationTokenJob $backgroundJob; protected function setUp(): void { parent::setUp(); @@ -56,14 +31,14 @@ class CleanupInvitationTokenJobTest extends TestCase { $this->dbConnection, $this->timeFactory); } - public function testRun() { + public function testRun(): void { $this->timeFactory->expects($this->once()) ->method('getTime') ->with() ->willReturn(1337); $queryBuilder = $this->createMock(IQueryBuilder::class); - $expr = $this->createMock(\OCP\DB\QueryBuilder\IExpressionBuilder::class); + $expr = $this->createMock(IExpressionBuilder::class); $stmt = $this->createMock(\Doctrine\DBAL\Driver\Statement::class); $this->dbConnection->expects($this->once()) @@ -77,25 +52,26 @@ class CleanupInvitationTokenJobTest extends TestCase { [1337, \PDO::PARAM_STR, null, 'namedParameter1337'] ]); + $function = 'function1337'; $expr->expects($this->once()) ->method('lt') ->with('expiration', 'namedParameter1337') - ->willReturn('LT STATEMENT'); + ->willReturn($function); $this->dbConnection->expects($this->once()) ->method('getQueryBuilder') ->with() ->willReturn($queryBuilder); - $queryBuilder->expects($this->at(0)) + $queryBuilder->expects($this->once()) ->method('delete') ->with('calendar_invitations') ->willReturn($queryBuilder); - $queryBuilder->expects($this->at(3)) + $queryBuilder->expects($this->once()) ->method('where') - ->with('LT STATEMENT') + ->with($function) ->willReturn($queryBuilder); - $queryBuilder->expects($this->at(4)) + $queryBuilder->expects($this->once()) ->method('execute') ->with() ->willReturn($stmt); diff --git a/apps/dav/tests/unit/BackgroundJob/CleanupOrphanedChildrenJobTest.php b/apps/dav/tests/unit/BackgroundJob/CleanupOrphanedChildrenJobTest.php new file mode 100644 index 00000000000..2065b8fe946 --- /dev/null +++ b/apps/dav/tests/unit/BackgroundJob/CleanupOrphanedChildrenJobTest.php @@ -0,0 +1,170 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\Tests\unit\BackgroundJob; + +use OCA\DAV\BackgroundJob\CleanupOrphanedChildrenJob; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\BackgroundJob\IJobList; +use OCP\DB\IResult; +use OCP\DB\QueryBuilder\IExpressionBuilder; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use Test\TestCase; + +class CleanupOrphanedChildrenJobTest extends TestCase { + private CleanupOrphanedChildrenJob $job; + + private ITimeFactory&MockObject $timeFactory; + private IDBConnection&MockObject $connection; + private LoggerInterface&MockObject $logger; + private IJobList&MockObject $jobList; + + protected function setUp(): void { + parent::setUp(); + + $this->timeFactory = $this->createMock(ITimeFactory::class); + $this->connection = $this->createMock(IDBConnection::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->jobList = $this->createMock(IJobList::class); + + $this->job = new CleanupOrphanedChildrenJob( + $this->timeFactory, + $this->connection, + $this->logger, + $this->jobList, + ); + } + + private function getArgument(): array { + return [ + 'childTable' => 'childTable', + 'parentTable' => 'parentTable', + 'parentId' => 'parentId', + 'logMessage' => 'logMessage', + ]; + } + + private function getMockQueryBuilder(): IQueryBuilder&MockObject { + $expr = $this->createMock(IExpressionBuilder::class); + $qb = $this->createMock(IQueryBuilder::class); + $qb->method('select') + ->willReturnSelf(); + $qb->method('from') + ->willReturnSelf(); + $qb->method('leftJoin') + ->willReturnSelf(); + $qb->method('where') + ->willReturnSelf(); + $qb->method('setMaxResults') + ->willReturnSelf(); + $qb->method('andWhere') + ->willReturnSelf(); + $qb->method('expr') + ->willReturn($expr); + $qb->method('delete') + ->willReturnSelf(); + return $qb; + } + + public function testRunWithoutOrphans(): void { + $argument = $this->getArgument(); + $selectQb = $this->getMockQueryBuilder(); + $result = $this->createMock(IResult::class); + + $this->connection->expects(self::once()) + ->method('getQueryBuilder') + ->willReturn($selectQb); + $selectQb->expects(self::once()) + ->method('executeQuery') + ->willReturn($result); + $result->expects(self::once()) + ->method('fetchAll') + ->willReturn([]); + $result->expects(self::once()) + ->method('closeCursor'); + $this->jobList->expects(self::never()) + ->method('add'); + + self::invokePrivate($this->job, 'run', [$argument]); + } + + public function testRunWithPartialBatch(): void { + $argument = $this->getArgument(); + $selectQb = $this->getMockQueryBuilder(); + $deleteQb = $this->getMockQueryBuilder(); + $result = $this->createMock(IResult::class); + + $calls = [ + $selectQb, + $deleteQb, + ]; + $this->connection->method('getQueryBuilder') + ->willReturnCallback(function () use (&$calls) { + return array_shift($calls); + }); + $selectQb->expects(self::once()) + ->method('executeQuery') + ->willReturn($result); + $result->expects(self::once()) + ->method('fetchAll') + ->willReturn([ + ['id' => 42], + ['id' => 43], + ]); + $result->expects(self::once()) + ->method('closeCursor'); + $deleteQb->expects(self::once()) + ->method('delete') + ->willReturnSelf(); + $deleteQb->expects(self::once()) + ->method('executeStatement'); + $this->jobList->expects(self::never()) + ->method('add'); + + self::invokePrivate($this->job, 'run', [$argument]); + } + + public function testRunWithFullBatch(): void { + $argument = $this->getArgument(); + $selectQb = $this->getMockQueryBuilder(); + $deleteQb = $this->getMockQueryBuilder(); + $result = $this->createMock(IResult::class); + + $calls = [ + $selectQb, + $deleteQb, + ]; + $this->connection->method('getQueryBuilder') + ->willReturnCallback(function () use (&$calls) { + return array_shift($calls); + }); + + $selectQb->expects(self::once()) + ->method('executeQuery') + ->willReturn($result); + $result->expects(self::once()) + ->method('fetchAll') + ->willReturn(array_map(static fn ($i) => ['id' => 42 + $i], range(0, 999))); + $result->expects(self::once()) + ->method('closeCursor'); + $deleteQb->expects(self::once()) + ->method('delete') + ->willReturnSelf(); + $deleteQb->expects(self::once()) + ->method('executeStatement'); + $this->jobList->expects(self::once()) + ->method('add') + ->with(CleanupOrphanedChildrenJob::class, $argument); + + self::invokePrivate($this->job, 'run', [$argument]); + } +} diff --git a/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php b/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php index ed3c324e710..a46a1e5e5b0 100644 --- a/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php +++ b/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php @@ -3,28 +3,8 @@ declare(strict_types=1); /** - * @copyright 2018, Thomas Citharel <tcit@tcit.fr> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Georg Ehrke <oc.list@georgehrke.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Citharel <nextcloud@tcit.fr> - * - * @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 OCA\DAV\Tests\unit\BackgroundJob; @@ -36,18 +16,10 @@ use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class EventReminderJobTest extends TestCase { - - /** @var ITimeFactory|MockObject */ - private $time; - - /** @var ReminderService|MockObject */ - private $reminderService; - - /** @var IConfig|MockObject */ - private $config; - - /** @var EventReminderJob|MockObject */ - private $backgroundJob; + private ITimeFactory&MockObject $time; + private ReminderService&MockObject $reminderService; + private IConfig&MockObject $config; + private EventReminderJob $backgroundJob; protected function setUp(): void { parent::setUp(); @@ -63,7 +35,7 @@ class EventReminderJobTest extends TestCase { ); } - public function data(): array { + public static function data(): array { return [ [true, true, true], [true, false, false], @@ -73,24 +45,19 @@ class EventReminderJobTest extends TestCase { } /** - * @dataProvider data * * @param bool $sendEventReminders * @param bool $sendEventRemindersMode * @param bool $expectCall */ + #[\PHPUnit\Framework\Attributes\DataProvider('data')] public function testRun(bool $sendEventReminders, bool $sendEventRemindersMode, bool $expectCall): void { - $this->config->expects($this->at(0)) + $this->config->expects($this->exactly($sendEventReminders ? 2 : 1)) ->method('getAppValue') - ->with('dav', 'sendEventReminders', 'yes') - ->willReturn($sendEventReminders ? 'yes' : 'no'); - - if ($sendEventReminders) { - $this->config->expects($this->at(1)) - ->method('getAppValue') - ->with('dav', 'sendEventRemindersMode', 'backgroundjob') - ->willReturn($sendEventRemindersMode ? 'backgroundjob' : 'cron'); - } + ->willReturnMap([ + ['dav', 'sendEventReminders', 'yes', ($sendEventReminders ? 'yes' : 'no')], + ['dav', 'sendEventRemindersMode', 'backgroundjob', ($sendEventRemindersMode ? 'backgroundjob' : 'cron')], + ]); if ($expectCall) { $this->reminderService->expects($this->once()) diff --git a/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php b/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php index e0601c5c71a..88a76ae1332 100644 --- a/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php +++ b/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php @@ -3,28 +3,8 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2017, Georg Ehrke - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Georg Ehrke <oc.list@georgehrke.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @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 OCA\DAV\Tests\unit\BackgroundJob; @@ -36,18 +16,10 @@ use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class GenerateBirthdayCalendarBackgroundJobTest extends TestCase { - - /** @var ITimeFactory|MockObject */ - private $time; - - /** @var BirthdayService | MockObject */ - private $birthdayService; - - /** @var IConfig | MockObject */ - private $config; - - /** @var \OCA\DAV\BackgroundJob\GenerateBirthdayCalendarBackgroundJob */ - private $backgroundJob; + private ITimeFactory&MockObject $time; + private BirthdayService&MockObject $birthdayService; + private IConfig&MockObject $config; + private GenerateBirthdayCalendarBackgroundJob $backgroundJob; protected function setUp(): void { parent::setUp(); @@ -63,7 +35,7 @@ class GenerateBirthdayCalendarBackgroundJobTest extends TestCase { ); } - public function testRun() { + public function testRun(): void { $this->config->expects($this->once()) ->method('getAppValue') ->with('dav', 'generateBirthdayCalendar', 'yes') @@ -85,7 +57,7 @@ class GenerateBirthdayCalendarBackgroundJobTest extends TestCase { $this->backgroundJob->run(['userId' => 'user123']); } - public function testRunAndReset() { + public function testRunAndReset(): void { $this->config->expects($this->once()) ->method('getAppValue') ->with('dav', 'generateBirthdayCalendar', 'yes') @@ -107,7 +79,7 @@ class GenerateBirthdayCalendarBackgroundJobTest extends TestCase { $this->backgroundJob->run(['userId' => 'user123', 'purgeBeforeGenerating' => true]); } - public function testRunGloballyDisabled() { + public function testRunGloballyDisabled(): void { $this->config->expects($this->once()) ->method('getAppValue') ->with('dav', 'generateBirthdayCalendar', 'yes') @@ -122,7 +94,7 @@ class GenerateBirthdayCalendarBackgroundJobTest extends TestCase { $this->backgroundJob->run(['userId' => 'user123']); } - public function testRunUserDisabled() { + public function testRunUserDisabled(): void { $this->config->expects($this->once()) ->method('getAppValue') ->with('dav', 'generateBirthdayCalendar', 'yes') diff --git a/apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php b/apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php new file mode 100644 index 00000000000..6135fd00fdc --- /dev/null +++ b/apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php @@ -0,0 +1,148 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\Tests\unit\BackgroundJob; + +use OCA\DAV\BackgroundJob\OutOfOfficeEventDispatcherJob; +use OCA\DAV\CalDAV\TimezoneService; +use OCA\DAV\Db\Absence; +use OCA\DAV\Db\AbsenceMapper; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\IUser; +use OCP\IUserManager; +use OCP\User\Events\OutOfOfficeEndedEvent; +use OCP\User\Events\OutOfOfficeStartedEvent; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use Test\TestCase; + +class OutOfOfficeEventDispatcherJobTest extends TestCase { + private OutOfOfficeEventDispatcherJob $job; + private ITimeFactory&MockObject $timeFactory; + private AbsenceMapper&MockObject $absenceMapper; + private LoggerInterface&MockObject $logger; + private IEventDispatcher&MockObject $eventDispatcher; + private IUserManager&MockObject $userManager; + private MockObject|TimezoneService $timezoneService; + + protected function setUp(): void { + parent::setUp(); + + $this->timeFactory = $this->createMock(ITimeFactory::class); + $this->absenceMapper = $this->createMock(AbsenceMapper::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->eventDispatcher = $this->createMock(IEventDispatcher::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->timezoneService = $this->createMock(TimezoneService::class); + + $this->job = new OutOfOfficeEventDispatcherJob( + $this->timeFactory, + $this->absenceMapper, + $this->logger, + $this->eventDispatcher, + $this->userManager, + $this->timezoneService, + ); + } + + public function testDispatchStartEvent(): void { + $this->timezoneService->method('getUserTimezone')->with('user')->willReturn('Europe/Berlin'); + + $absence = new Absence(); + $absence->setId(200); + $absence->setUserId('user'); + + $user = $this->createMock(IUser::class); + $user->method('getUID') + ->willReturn('user'); + + $this->absenceMapper->expects(self::once()) + ->method('findById') + ->with(1) + ->willReturn($absence); + $this->userManager->expects(self::once()) + ->method('get') + ->with('user') + ->willReturn($user); + $this->eventDispatcher->expects(self::once()) + ->method('dispatchTyped') + ->with(self::callback(static function ($event): bool { + self::assertInstanceOf(OutOfOfficeStartedEvent::class, $event); + return true; + })); + + $this->job->run([ + 'id' => 1, + 'event' => OutOfOfficeEventDispatcherJob::EVENT_START, + ]); + } + + public function testDispatchStopEvent(): void { + $this->timezoneService->method('getUserTimezone')->with('user')->willReturn('Europe/Berlin'); + + $absence = new Absence(); + $absence->setId(200); + $absence->setUserId('user'); + + $user = $this->createMock(IUser::class); + $user->method('getUID') + ->willReturn('user'); + + $this->absenceMapper->expects(self::once()) + ->method('findById') + ->with(1) + ->willReturn($absence); + $this->userManager->expects(self::once()) + ->method('get') + ->with('user') + ->willReturn($user); + $this->eventDispatcher->expects(self::once()) + ->method('dispatchTyped') + ->with(self::callback(static function ($event): bool { + self::assertInstanceOf(OutOfOfficeEndedEvent::class, $event); + return true; + })); + + $this->job->run([ + 'id' => 1, + 'event' => OutOfOfficeEventDispatcherJob::EVENT_END, + ]); + } + + public function testDoesntDispatchUnknownEvent(): void { + $this->timezoneService->method('getUserTimezone')->with('user')->willReturn('Europe/Berlin'); + + $absence = new Absence(); + $absence->setId(100); + $absence->setUserId('user'); + + $user = $this->createMock(IUser::class); + $user->method('getUID') + ->willReturn('user'); + + $this->absenceMapper->expects(self::once()) + ->method('findById') + ->with(1) + ->willReturn($absence); + $this->userManager->expects(self::once()) + ->method('get') + ->with('user') + ->willReturn($user); + $this->eventDispatcher->expects(self::never()) + ->method('dispatchTyped'); + $this->logger->expects(self::once()) + ->method('error'); + + $this->job->run([ + 'id' => 1, + 'event' => 'foobar', + ]); + } +} diff --git a/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php b/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php new file mode 100644 index 00000000000..1838fb2537d --- /dev/null +++ b/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php @@ -0,0 +1,82 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\DAV\Tests\unit\BackgroundJob; + +use InvalidArgumentException; +use OCA\DAV\AppInfo\Application; +use OCA\DAV\BackgroundJob\PruneOutdatedSyncTokensJob; +use OCA\DAV\CalDAV\CalDavBackend; +use OCA\DAV\CardDAV\CardDavBackend; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\IConfig; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use Test\TestCase; + +class PruneOutdatedSyncTokensJobTest extends TestCase { + private ITimeFactory&MockObject $timeFactory; + private CalDavBackend&MockObject $calDavBackend; + private CardDavBackend&MockObject $cardDavBackend; + private IConfig&MockObject $config; + private LoggerInterface&MockObject $logger; + private PruneOutdatedSyncTokensJob $backgroundJob; + + protected function setUp(): void { + parent::setUp(); + + $this->timeFactory = $this->createMock(ITimeFactory::class); + $this->calDavBackend = $this->createMock(CalDavBackend::class); + $this->cardDavBackend = $this->createMock(CardDavBackend::class); + $this->config = $this->createMock(IConfig::class); + $this->logger = $this->createMock(LoggerInterface::class); + + $this->backgroundJob = new PruneOutdatedSyncTokensJob($this->timeFactory, $this->calDavBackend, $this->cardDavBackend, $this->config, $this->logger); + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataForTestRun')] + public function testRun(string $configToKeep, string $configRetentionDays, int $actualLimit, int $retentionDays, int $deletedCalendarSyncTokens, int $deletedAddressBookSyncTokens): void { + $this->config->expects($this->exactly(2)) + ->method('getAppValue') + ->with(Application::APP_ID, self::anything(), self::anything()) + ->willReturnCallback(function ($app, $key) use ($configToKeep, $configRetentionDays) { + switch ($key) { + case 'totalNumberOfSyncTokensToKeep': + return $configToKeep; + case 'syncTokensRetentionDays': + return $configRetentionDays; + default: + throw new InvalidArgumentException(); + } + }); + $this->calDavBackend->expects($this->once()) + ->method('pruneOutdatedSyncTokens') + ->with($actualLimit) + ->willReturn($deletedCalendarSyncTokens); + $this->cardDavBackend->expects($this->once()) + ->method('pruneOutdatedSyncTokens') + ->with($actualLimit, $retentionDays) + ->willReturn($deletedAddressBookSyncTokens); + $this->logger->expects($this->once()) + ->method('info') + ->with('Pruned {calendarSyncTokensNumber} calendar sync tokens and {addressBooksSyncTokensNumber} address book sync tokens', [ + 'calendarSyncTokensNumber' => $deletedCalendarSyncTokens, + 'addressBooksSyncTokensNumber' => $deletedAddressBookSyncTokens + ]); + + $this->backgroundJob->run(null); + } + + public static function dataForTestRun(): array { + return [ + ['100', '2', 100, 7 * 24 * 3600, 2, 3], + ['100', '14', 100, 14 * 24 * 3600, 2, 3], + ['0', '60', 1, 60 * 24 * 3600, 0, 0] + ]; + } +} diff --git a/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php b/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php index 360c4c791c7..7713ef2945a 100644 --- a/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php +++ b/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php @@ -3,28 +3,8 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2018, Georg Ehrke - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Georg Ehrke <oc.list@georgehrke.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Citharel <nextcloud@tcit.fr> - * - * @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 OCA\DAV\Tests\unit\BackgroundJob; @@ -33,34 +13,24 @@ use OCA\DAV\CalDAV\WebcalCaching\RefreshWebcalService; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\IJobList; use OCP\IConfig; -use OCP\ILogger; use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; class RefreshWebcalJobTest extends TestCase { - - /** @var RefreshWebcalService | MockObject */ - private $refreshWebcalService; - - /** @var IConfig | MockObject */ - private $config; - - /** @var ILogger | MockObject */ - private $logger; - - /** @var ITimeFactory | MockObject */ - private $timeFactory; - - /** @var IJobList | MockObject */ - private $jobList; + private RefreshWebcalService&MockObject $refreshWebcalService; + private IConfig&MockObject $config; + private LoggerInterface $logger; + private ITimeFactory&MockObject $timeFactory; + private IJobList&MockObject $jobList; protected function setUp(): void { parent::setUp(); $this->refreshWebcalService = $this->createMock(RefreshWebcalService::class); $this->config = $this->createMock(IConfig::class); - $this->logger = $this->createMock(ILogger::class); + $this->logger = $this->createMock(LoggerInterface::class); $this->timeFactory = $this->createMock(ITimeFactory::class); $this->jobList = $this->createMock(IJobList::class); @@ -71,10 +41,9 @@ class RefreshWebcalJobTest extends TestCase { * @param int $lastRun * @param int $time * @param bool $process - * - * @dataProvider runDataProvider */ - public function testRun(int $lastRun, int $time, bool $process) { + #[\PHPUnit\Framework\Attributes\DataProvider('runDataProvider')] + public function testRun(int $lastRun, int $time, bool $process): void { $backgroundJob = new RefreshWebcalJob($this->refreshWebcalService, $this->config, $this->logger, $this->timeFactory); $backgroundJob->setId(42); @@ -99,7 +68,7 @@ class RefreshWebcalJobTest extends TestCase { $this->config->expects($this->once()) ->method('getAppValue') - ->with('dav', 'calendarSubscriptionRefreshRate', 'P1W') + ->with('dav', 'calendarSubscriptionRefreshRate', 'P1D') ->willReturn('P1W'); $this->timeFactory->method('getTime') @@ -115,13 +84,10 @@ class RefreshWebcalJobTest extends TestCase { ->with('principals/users/testuser', 'sub123'); } - $backgroundJob->execute($this->jobList, $this->logger); + $backgroundJob->start($this->jobList); } - /** - * @return array - */ - public function runDataProvider():array { + public static function runDataProvider():array { return [ [0, 100000, true], [100000, 100000, false] diff --git a/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php b/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php index 00931d53f64..6c9214d0268 100644 --- a/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php +++ b/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php @@ -3,28 +3,8 @@ declare(strict_types=1); /** - * @copyright 2019 Georg Ehrke <oc.list@georgehrke.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Georg Ehrke <oc.list@georgehrke.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @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 OCA\DAV\Tests\unit\BackgroundJob; @@ -32,24 +12,16 @@ use OCA\DAV\BackgroundJob\GenerateBirthdayCalendarBackgroundJob; use OCA\DAV\BackgroundJob\RegisterRegenerateBirthdayCalendars; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\IJobList; -use OCP\IConfig; use OCP\IUser; use OCP\IUserManager; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class RegisterRegenerateBirthdayCalendarsTest extends TestCase { - - /** @var ITimeFactory | \PHPUnit\Framework\MockObject\MockObject */ - private $time; - - /** @var IUserManager | \PHPUnit\Framework\MockObject\MockObject */ - private $userManager; - - /** @var IJobList | \PHPUnit\Framework\MockObject\MockObject */ - private $jobList; - - /** @var RegisterRegenerateBirthdayCalendars */ - private $backgroundJob; + private ITimeFactory&MockObject $time; + private IUserManager&MockObject $userManager; + private IJobList&MockObject $jobList; + private RegisterRegenerateBirthdayCalendars $backgroundJob; protected function setUp(): void { parent::setUp(); @@ -65,10 +37,10 @@ class RegisterRegenerateBirthdayCalendarsTest extends TestCase { ); } - public function testRun() { + public function testRun(): void { $this->userManager->expects($this->once()) ->method('callForSeenUsers') - ->willReturnCallback(function ($closure) { + ->willReturnCallback(function ($closure): void { $user1 = $this->createMock(IUser::class); $user1->method('getUID')->willReturn('uid1'); $user2 = $this->createMock(IUser::class); @@ -81,24 +53,26 @@ class RegisterRegenerateBirthdayCalendarsTest extends TestCase { $closure($user3); }); - $this->jobList->expects($this->at(0)) + $calls = [ + 'uid1', + 'uid2', + 'uid3', + ]; + $this->jobList->expects($this->exactly(3)) ->method('add') - ->with(GenerateBirthdayCalendarBackgroundJob::class, [ - 'userId' => 'uid1', - 'purgeBeforeGenerating' => true - ]); - $this->jobList->expects($this->at(1)) - ->method('add') - ->with(GenerateBirthdayCalendarBackgroundJob::class, [ - 'userId' => 'uid2', - 'purgeBeforeGenerating' => true - ]); - $this->jobList->expects($this->at(2)) - ->method('add') - ->with(GenerateBirthdayCalendarBackgroundJob::class, [ - 'userId' => 'uid3', - 'purgeBeforeGenerating' => true - ]); + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals( + [ + GenerateBirthdayCalendarBackgroundJob::class, + [ + 'userId' => $expected, + 'purgeBeforeGenerating' => true + ] + ], + func_get_args() + ); + }); $this->backgroundJob->run([]); } diff --git a/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php b/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php index 59b68452862..38a981787cd 100644 --- a/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php +++ b/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php @@ -3,64 +3,24 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2018, Georg Ehrke - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Georg Ehrke <oc.list@georgehrke.com> - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @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 OCA\DAV\Tests\unit\BackgroundJob; use OCA\DAV\BackgroundJob\UpdateCalendarResourcesRoomsBackgroundJob; -use OCA\DAV\CalDAV\CalDavBackend; use OCP\AppFramework\Utility\ITimeFactory; -use OCP\Calendar\BackendTemporarilyUnavailableException; -use OCP\Calendar\IMetadataProvider; -use OCP\Calendar\Resource\IBackend; use OCP\Calendar\Resource\IManager as IResourceManager; -use OCP\Calendar\Resource\IResource; use OCP\Calendar\Room\IManager as IRoomManager; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; -interface tmpI extends IResource, IMetadataProvider { -} - class UpdateCalendarResourcesRoomsBackgroundJobTest extends TestCase { - - /** @var ITimeFactory|MockObject */ - private $time; - - /** @var IResourceManager|MockObject */ - private $resourceManager; - - /** @var IRoomManager|MockObject */ - private $roomManager; - - /** @var CalDavBackend|MockObject */ - private $calDavBackend; - - /** @var UpdateCalendarResourcesRoomsBackgroundJob */ - private $backgroundJob; + private UpdateCalendarResourcesRoomsBackgroundJob $backgroundJob; + private ITimeFactory&MockObject $time; + private IResourceManager&MockObject $resourceManager; + private IRoomManager&MockObject $roomManager; protected function setUp(): void { parent::setUp(); @@ -68,390 +28,20 @@ class UpdateCalendarResourcesRoomsBackgroundJobTest extends TestCase { $this->time = $this->createMock(ITimeFactory::class); $this->resourceManager = $this->createMock(IResourceManager::class); $this->roomManager = $this->createMock(IRoomManager::class); - $this->calDavBackend = $this->createMock(CalDavBackend::class); $this->backgroundJob = new UpdateCalendarResourcesRoomsBackgroundJob( $this->time, $this->resourceManager, $this->roomManager, - self::$realDatabase, - $this->calDavBackend ); } - protected function tearDown(): void { - $query = self::$realDatabase->getQueryBuilder(); - $query->delete('calendar_resources')->execute(); - $query->delete('calendar_resources_md')->execute(); - $query->delete('calendar_rooms')->execute(); - $query->delete('calendar_rooms_md')->execute(); - } - - /** - * Data in Cache: - * resources: - * [backend1, res1, Beamer1, {}] - [] - * [backend1, res2, TV1, {}] - [] - * [backend2, res3, Beamer2, {}] - ['meta1' => 'value1', 'meta2' => 'value2'] - * [backend2, res4, TV2, {}] - ['meta1' => 'value1', 'meta3' => 'value3-old'] - * [backend3, res5, Beamer3, {}] - [] - * [backend3, res6, Pointer, {foo, bar}] - ['meta99' => 'value99'] - * - * Data in Backend: - * backend1 gone - * backend2 throws BackendTemporarilyUnavailableException - * [backend3, res6, Pointer123, {foo, biz}] - ['meta99' => 'value99-new', 'meta123' => 'meta456'] - * [backend3, res7, Resource4, {biz}] - ['meta1' => 'value1'] - * [backend4, res8, Beamer, {}] - ['meta2' => 'value2'] - * [backend4, res9, Beamer2, {}] - [] - * - * Expected after run: - * [backend1, res1, Beamer1, {}] - [] - * [backend1, res2, TV1, {}] - [] - * [backend2, res3, Beamer2, {}] - ['meta1' => 'value1', 'meta2' => 'value2'] - * [backend2, res4, TV2, {}] - ['meta1' => 'value1', 'meta3' => 'value3-old'] - * [backend3, res6, Pointer123, {foo, biz}] - ['meta99' => 'value99-new', 'meta123' => 'meta456'] - * [backend3, res7, Resource4, {biz}] - ['meta1' => 'value1'] - * [backend4, res8, Beamer, {}] - ['meta2' => 'value2'] - * [backend4, res9, Beamer2, {}] - [] - */ - - public function testRun() { - $this->createTestResourcesInCache(); - - $backend2 = $this->createMock(IBackend::class); - $backend3 = $this->createMock(IBackend::class); - $backend4 = $this->createMock(IBackend::class); - - $res6 = $this->createMock(tmpI::class); - $res7 = $this->createMock(tmpI::class); - $res8 = $this->createMock(tmpI::class); - $res9 = $this->createMock(IResource::class); - - $backend2->method('getBackendIdentifier') - ->willReturn('backend2'); - $backend2->method('listAllResources') - ->will($this->throwException(new BackendTemporarilyUnavailableException())); - $backend2->method('getResource') - ->will($this->throwException(new BackendTemporarilyUnavailableException())); - $backend2->method('getAllResources') - ->will($this->throwException(new BackendTemporarilyUnavailableException())); - $backend3->method('getBackendIdentifier') - ->willReturn('backend3'); - $backend3->method('listAllResources') - ->willReturn(['res6', 'res7']); - $backend3->method('getResource') - ->willReturnMap([ - ['res6', $res6], - ['res7', $res7], - ]); - $backend4->method('getBackendIdentifier') - ->willReturn('backend4'); - $backend4->method('listAllResources') - ->willReturn(['res8', 'res9']); - $backend4->method('getResource') - ->willReturnMap([ - ['res8', $res8], - ['res9', $res9], - ]); - - $res6->method('getId')->willReturn('res6'); - $res6->method('getDisplayName')->willReturn('Pointer123'); - $res6->method('getGroupRestrictions')->willReturn(['foo', 'biz']); - $res6->method('getEMail')->willReturn('res6@foo.bar'); - $res6->method('getBackend')->willReturn($backend3); - - $res6->method('getAllAvailableMetadataKeys')->willReturn(['meta99', 'meta123']); - $res6->method('getMetadataForKey')->willReturnCallback(function ($key) { - switch ($key) { - case 'meta99': - return 'value99-new'; - - case 'meta123': - return 'meta456'; - - default: - return null; - } - }); - - $res7->method('getId')->willReturn('res7'); - $res7->method('getDisplayName')->willReturn('Resource4'); - $res7->method('getGroupRestrictions')->willReturn(['biz']); - $res7->method('getEMail')->willReturn('res7@foo.bar'); - $res7->method('getBackend')->willReturn($backend3); - $res7->method('getAllAvailableMetadataKeys')->willReturn(['meta1']); - $res7->method('getMetadataForKey')->willReturnCallback(function ($key) { - switch ($key) { - case 'meta1': - return 'value1'; - - default: - return null; - } - }); - - $res8->method('getId')->willReturn('res8'); - $res8->method('getDisplayName')->willReturn('Beamer'); - $res8->method('getGroupRestrictions')->willReturn([]); - $res8->method('getEMail')->willReturn('res8@foo.bar'); - $res8->method('getBackend')->willReturn($backend4); - $res8->method('getAllAvailableMetadataKeys')->willReturn(['meta2']); - $res8->method('getMetadataForKey')->willReturnCallback(function ($key) { - switch ($key) { - case 'meta2': - return 'value2'; - - default: - return null; - } - }); - - $res9->method('getId')->willReturn('res9'); - $res9->method('getDisplayName')->willReturn('Beamer2'); - $res9->method('getGroupRestrictions')->willReturn([]); - $res9->method('getEMail')->willReturn('res9@foo.bar'); - $res9->method('getBackend')->willReturn($backend4); - - $this->resourceManager - ->method('getBackends') - ->willReturn([ - $backend2, $backend3, $backend4 - ]); - $this->resourceManager - ->method('getBackend') - ->willReturnMap([ - ['backend2', $backend2], - ['backend3', $backend3], - ['backend4', $backend4], - ]); + public function testRun(): void { + $this->resourceManager->expects(self::once()) + ->method('update'); + $this->roomManager->expects(self::once()) + ->method('update'); $this->backgroundJob->run([]); - - $query = self::$realDatabase->getQueryBuilder(); - $query->select('*')->from('calendar_resources'); - - $rows = []; - $ids = []; - $stmt = $query->execute(); - while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { - $ids[$row['backend_id'] . '::' . $row['resource_id']] = $row['id']; - unset($row['id']); - $rows[] = $row; - } - - $this->assertEquals([ - [ - 'backend_id' => 'backend1', - 'resource_id' => 'res1', - 'displayname' => 'Beamer1', - 'email' => 'res1@foo.bar', - 'group_restrictions' => '[]', - ], - [ - 'backend_id' => 'backend1', - 'resource_id' => 'res2', - 'displayname' => 'TV1', - 'email' => 'res2@foo.bar', - 'group_restrictions' => '[]', - ], - [ - 'backend_id' => 'backend2', - 'resource_id' => 'res3', - 'displayname' => 'Beamer2', - 'email' => 'res3@foo.bar', - 'group_restrictions' => '[]', - ], - [ - 'backend_id' => 'backend2', - 'resource_id' => 'res4', - 'displayname' => 'TV2', - 'email' => 'res4@foo.bar', - 'group_restrictions' => '[]', - ], - [ - 'backend_id' => 'backend3', - 'resource_id' => 'res6', - 'displayname' => 'Pointer123', - 'email' => 'res6@foo.bar', - 'group_restrictions' => '["foo","biz"]', - ], - [ - 'backend_id' => 'backend3', - 'resource_id' => 'res7', - 'displayname' => 'Resource4', - 'email' => 'res7@foo.bar', - 'group_restrictions' => '["biz"]', - ], - [ - 'backend_id' => 'backend4', - 'resource_id' => 'res8', - 'displayname' => 'Beamer', - 'email' => 'res8@foo.bar', - 'group_restrictions' => '[]', - ], - [ - 'backend_id' => 'backend4', - 'resource_id' => 'res9', - 'displayname' => 'Beamer2', - 'email' => 'res9@foo.bar', - 'group_restrictions' => '[]', - ], - ], $rows); - - $query2 = self::$realDatabase->getQueryBuilder(); - $query2->select('*')->from('calendar_resources_md'); - - $rows2 = []; - $stmt = $query2->execute(); - while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { - unset($row['id']); - $rows2[] = $row; - } - - $this->assertEquals([ - [ - 'resource_id' => $ids['backend2::res3'], - 'key' => 'meta1', - 'value' => 'value1', - ], - [ - 'resource_id' => $ids['backend2::res3'], - 'key' => 'meta2', - 'value' => 'value2', - ], - [ - 'resource_id' => $ids['backend2::res4'], - 'key' => 'meta1', - 'value' => 'value1', - ], - [ - 'resource_id' => $ids['backend2::res4'], - 'key' => 'meta3', - 'value' => 'value3-old', - ], - [ - 'resource_id' => $ids['backend3::res6'], - 'key' => 'meta99', - 'value' => 'value99-new', - ], - [ - 'resource_id' => $ids['backend3::res7'], - 'key' => 'meta1', - 'value' => 'value1', - ], - [ - 'resource_id' => $ids['backend3::res6'], - 'key' => 'meta123', - 'value' => 'meta456', - ], - [ - 'resource_id' => $ids['backend4::res8'], - 'key' => 'meta2', - 'value' => 'value2', - ] - ], $rows2); - } - - protected function createTestResourcesInCache() { - $query = self::$realDatabase->getQueryBuilder(); - $query->insert('calendar_resources') - ->values([ - 'backend_id' => $query->createNamedParameter('backend1'), - 'resource_id' => $query->createNamedParameter('res1'), - 'email' => $query->createNamedParameter('res1@foo.bar'), - 'displayname' => $query->createNamedParameter('Beamer1'), - 'group_restrictions' => $query->createNamedParameter('[]'), - ]) - ->execute(); - - $query->insert('calendar_resources') - ->values([ - 'backend_id' => $query->createNamedParameter('backend1'), - 'resource_id' => $query->createNamedParameter('res2'), - 'email' => $query->createNamedParameter('res2@foo.bar'), - 'displayname' => $query->createNamedParameter('TV1'), - 'group_restrictions' => $query->createNamedParameter('[]'), - ]) - ->execute(); - - $query->insert('calendar_resources') - ->values([ - 'backend_id' => $query->createNamedParameter('backend2'), - 'resource_id' => $query->createNamedParameter('res3'), - 'email' => $query->createNamedParameter('res3@foo.bar'), - 'displayname' => $query->createNamedParameter('Beamer2'), - 'group_restrictions' => $query->createNamedParameter('[]'), - ]) - ->execute(); - $id3 = $query->getLastInsertId(); - - $query->insert('calendar_resources') - ->values([ - 'backend_id' => $query->createNamedParameter('backend2'), - 'resource_id' => $query->createNamedParameter('res4'), - 'email' => $query->createNamedParameter('res4@foo.bar'), - 'displayname' => $query->createNamedParameter('TV2'), - 'group_restrictions' => $query->createNamedParameter('[]'), - ]) - ->execute(); - $id4 = $query->getLastInsertId(); - - $query->insert('calendar_resources') - ->values([ - 'backend_id' => $query->createNamedParameter('backend3'), - 'resource_id' => $query->createNamedParameter('res5'), - 'email' => $query->createNamedParameter('res5@foo.bar'), - 'displayname' => $query->createNamedParameter('Beamer3'), - 'group_restrictions' => $query->createNamedParameter('[]'), - ]) - ->execute(); - - $query->insert('calendar_resources') - ->values([ - 'backend_id' => $query->createNamedParameter('backend3'), - 'resource_id' => $query->createNamedParameter('res6'), - 'email' => $query->createNamedParameter('res6@foo.bar'), - 'displayname' => $query->createNamedParameter('Pointer'), - 'group_restrictions' => $query->createNamedParameter('["foo", "bar"]'), - ]) - ->execute(); - $id6 = $query->getLastInsertId(); - - $query->insert('calendar_resources_md') - ->values([ - 'resource_id' => $query->createNamedParameter($id3), - 'key' => $query->createNamedParameter('meta1'), - 'value' => $query->createNamedParameter('value1') - ]) - ->execute(); - $query->insert('calendar_resources_md') - ->values([ - 'resource_id' => $query->createNamedParameter($id3), - 'key' => $query->createNamedParameter('meta2'), - 'value' => $query->createNamedParameter('value2') - ]) - ->execute(); - $query->insert('calendar_resources_md') - ->values([ - 'resource_id' => $query->createNamedParameter($id4), - 'key' => $query->createNamedParameter('meta1'), - 'value' => $query->createNamedParameter('value1') - ]) - ->execute(); - $query->insert('calendar_resources_md') - ->values([ - 'resource_id' => $query->createNamedParameter($id4), - 'key' => $query->createNamedParameter('meta3'), - 'value' => $query->createNamedParameter('value3-old') - ]) - ->execute(); - $query->insert('calendar_resources_md') - ->values([ - 'resource_id' => $query->createNamedParameter($id6), - 'key' => $query->createNamedParameter('meta99'), - 'value' => $query->createNamedParameter('value99') - ]) - ->execute(); } } diff --git a/apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php b/apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php new file mode 100644 index 00000000000..d49d20180d9 --- /dev/null +++ b/apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php @@ -0,0 +1,220 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\Tests\unit\BackgroundJob; + +use OC\User\OutOfOfficeData; +use OCA\DAV\BackgroundJob\UserStatusAutomation; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\BackgroundJob\IJobList; +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\IUser; +use OCP\IUserManager; +use OCP\Server; +use OCP\User\IAvailabilityCoordinator; +use OCP\UserStatus\IManager; +use OCP\UserStatus\IUserStatus; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use Test\TestCase; + +/** + * @group DB + */ +class UserStatusAutomationTest extends TestCase { + protected ITimeFactory&MockObject $time; + protected IJobList&MockObject $jobList; + protected LoggerInterface&MockObject $logger; + protected IManager&MockObject $statusManager; + protected IConfig&MockObject $config; + private IAvailabilityCoordinator&MockObject $coordinator; + private IUserManager&MockObject $userManager; + + protected function setUp(): void { + parent::setUp(); + + $this->time = $this->createMock(ITimeFactory::class); + $this->jobList = $this->createMock(IJobList::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->statusManager = $this->createMock(IManager::class); + $this->config = $this->createMock(IConfig::class); + $this->coordinator = $this->createMock(IAvailabilityCoordinator::class); + $this->userManager = $this->createMock(IUserManager::class); + + } + + protected function getAutomationMock(array $methods): MockObject|UserStatusAutomation { + if (empty($methods)) { + return new UserStatusAutomation( + $this->time, + Server::get(IDBConnection::class), + $this->jobList, + $this->logger, + $this->statusManager, + $this->config, + $this->coordinator, + $this->userManager, + ); + } + + return $this->getMockBuilder(UserStatusAutomation::class) + ->setConstructorArgs([ + $this->time, + Server::get(IDBConnection::class), + $this->jobList, + $this->logger, + $this->statusManager, + $this->config, + $this->coordinator, + $this->userManager, + ]) + ->onlyMethods($methods) + ->getMock(); + } + + public static function dataRun(): array { + return [ + ['20230217', '2023-02-24 10:49:36.613834', true], + ['20230224', '2023-02-24 10:49:36.613834', true], + ['20230217', '2023-02-24 13:58:24.479357', false], + ['20230224', '2023-02-24 13:58:24.479357', false], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataRun')] + public function testRunNoOOO(string $ruleDay, string $currentTime, bool $isAvailable): void { + $user = $this->createConfiguredMock(IUser::class, [ + 'getUID' => 'user' + ]); + + $this->userManager->expects(self::once()) + ->method('get') + ->willReturn($user); + $this->coordinator->expects(self::once()) + ->method('getCurrentOutOfOfficeData') + ->willReturn(null); + $this->config->method('getUserValue') + ->with('user', 'dav', 'user_status_automation', 'no') + ->willReturn('yes'); + $this->time->method('getDateTime') + ->willReturn(new \DateTime($currentTime, new \DateTimeZone('UTC'))); + $this->logger->expects(self::exactly(4)) + ->method('debug'); + if (!$isAvailable) { + $this->statusManager->expects(self::once()) + ->method('setUserStatus') + ->with('user', IUserStatus::MESSAGE_AVAILABILITY, IUserStatus::DND, true); + } + $automation = $this->getAutomationMock(['getAvailabilityFromPropertiesTable']); + $automation->method('getAvailabilityFromPropertiesTable') + ->with('user') + ->willReturn('BEGIN:VCALENDAR +PRODID:Nextcloud DAV app +BEGIN:VTIMEZONE +TZID:Europe/Berlin +BEGIN:STANDARD +TZNAME:CET +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +DTSTART:19701025T030000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +END:STANDARD +BEGIN:DAYLIGHT +TZNAME:CEST +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +DTSTART:19700329T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU +END:DAYLIGHT +END:VTIMEZONE +BEGIN:VAVAILABILITY +BEGIN:AVAILABLE +DTSTART;TZID=Europe/Berlin:' . $ruleDay . 'T090000 +DTEND;TZID=Europe/Berlin:' . $ruleDay . 'T170000 +UID:3e6feeec-8e00-4265-b822-b73174e8b39f +RRULE:FREQ=WEEKLY;BYDAY=TH +END:AVAILABLE +BEGIN:AVAILABLE +DTSTART;TZID=Europe/Berlin:' . $ruleDay . 'T090000 +DTEND;TZID=Europe/Berlin:' . $ruleDay . 'T120000 +UID:8a634e99-07cf-443b-b480-005a0e1db323 +RRULE:FREQ=WEEKLY;BYDAY=FR +END:AVAILABLE +END:VAVAILABILITY +END:VCALENDAR'); + + self::invokePrivate($automation, 'run', [['userId' => 'user']]); + } + + public function testRunNoAvailabilityNoOOO(): void { + $user = $this->createConfiguredMock(IUser::class, [ + 'getUID' => 'user' + ]); + + $this->userManager->expects(self::once()) + ->method('get') + ->willReturn($user); + $this->coordinator->expects(self::once()) + ->method('getCurrentOutOfOfficeData') + ->willReturn(null); + $this->config->method('getUserValue') + ->with('user', 'dav', 'user_status_automation', 'no') + ->willReturn('yes'); + $this->time->method('getDateTime') + ->willReturn(new \DateTime('2023-02-24 13:58:24.479357', new \DateTimeZone('UTC'))); + $this->jobList->expects($this->once()) + ->method('remove') + ->with(UserStatusAutomation::class, ['userId' => 'user']); + $this->logger->expects(self::once()) + ->method('debug'); + $this->logger->expects(self::once()) + ->method('info'); + $automation = $this->getAutomationMock(['getAvailabilityFromPropertiesTable']); + $automation->method('getAvailabilityFromPropertiesTable') + ->with('user') + ->willReturn(false); + + self::invokePrivate($automation, 'run', [['userId' => 'user']]); + } + + public function testRunNoAvailabilityWithOOO(): void { + $user = $this->createConfiguredMock(IUser::class, [ + 'getUID' => 'user' + ]); + $ooo = $this->createConfiguredMock(OutOfOfficeData::class, [ + 'getShortMessage' => 'On Vacation', + 'getEndDate' => 123456, + ]); + + $this->userManager->expects(self::once()) + ->method('get') + ->willReturn($user); + $this->coordinator->expects(self::once()) + ->method('getCurrentOutOfOfficeData') + ->willReturn($ooo); + $this->coordinator->expects(self::once()) + ->method('isInEffect') + ->willReturn(true); + $this->statusManager->expects(self::once()) + ->method('setUserStatus') + ->with('user', IUserStatus::MESSAGE_OUT_OF_OFFICE, IUserStatus::DND, true, $ooo->getShortMessage()); + $this->config->expects(self::never()) + ->method('getUserValue'); + $this->time->method('getDateTime') + ->willReturn(new \DateTime('2023-02-24 13:58:24.479357', new \DateTimeZone('UTC'))); + $this->jobList->expects($this->never()) + ->method('remove'); + $this->logger->expects(self::exactly(2)) + ->method('debug'); + $automation = $this->getAutomationMock([]); + + self::invokePrivate($automation, 'run', [['userId' => 'user']]); + } +} |