diff options
Diffstat (limited to 'apps/dav/tests/unit')
6 files changed, 235 insertions, 0 deletions
diff --git a/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php b/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php index d4021a66299..cafbdd3ca40 100644 --- a/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php @@ -12,6 +12,7 @@ use OCA\DAV\CalDAV\DefaultCalendarValidator; use OCA\DAV\Connector\Sabre\Directory; use OCA\DAV\Connector\Sabre\File; use OCA\DAV\DAV\CustomPropertiesBackend; +use OCA\DAV\Db\PropertyMapper; use OCP\IDBConnection; use OCP\IUser; use OCP\Server; @@ -52,6 +53,7 @@ class CustomPropertiesBackendTest extends \Test\TestCase { $this->tree, Server::get(IDBConnection::class), $this->user, + Server::get(PropertyMapper::class), $this->defaultCalendarValidator, ); } diff --git a/apps/dav/tests/unit/Connector/Sabre/PropFindMonitorPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/PropFindMonitorPluginTest.php new file mode 100644 index 00000000000..9d22befa201 --- /dev/null +++ b/apps/dav/tests/unit/Connector/Sabre/PropFindMonitorPluginTest.php @@ -0,0 +1,133 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace unit\Connector\Sabre; + +use OCA\DAV\Connector\Sabre\PropFindMonitorPlugin; +use OCA\DAV\Connector\Sabre\Server; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use Sabre\HTTP\Request; +use Sabre\HTTP\Response; +use Test\TestCase; + +class PropFindMonitorPluginTest extends TestCase { + + private PropFindMonitorPlugin $plugin; + private Server&MockObject $server; + private LoggerInterface&MockObject $logger; + private Request&MockObject $request; + private Response&MockObject $response; + + public static function dataTest(): array { + $minQueriesTrigger = PropFindMonitorPlugin::THRESHOLD_QUERY_FACTOR + * PropFindMonitorPlugin::THRESHOLD_NODES; + return [ + 'No queries logged' => [[], 0], + 'Plugins with queries in less than threshold nodes should not be logged' => [ + [ + 'propFind' => [ + [ + 'PluginName' => [ + 'queries' => 100, + 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES - 1] + ], + [], + ] + ], + 0 + ], + 'Plugins with query-to-node ratio less than threshold should not be logged' => [ + [ + 'propFind' => [ + [ + 'PluginName' => [ + 'queries' => $minQueriesTrigger - 1, + 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES ], + ], + [], + ] + ], + 0 + ], + 'Plugins with more nodes scanned than queries executed should not be logged' => [ + [ + 'propFind' => [ + [ + 'PluginName' => [ + 'queries' => $minQueriesTrigger, + 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES * 2], + ], + [],] + ], + 0 + ], + 'Plugins with queries only in highest depth level should not be logged' => [ + [ + 'propFind' => [ + [ + 'PluginName' => [ + 'queries' => $minQueriesTrigger, + 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES - 1 + ] + ], + [ + 'PluginName' => [ + 'queries' => $minQueriesTrigger * 2, + 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES + ] + ], + ] + ], + 0 + ], + 'Plugins with too many queries should be logged' => [ + [ + 'propFind' => [ + [ + 'FirstPlugin' => [ + 'queries' => $minQueriesTrigger, + 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES, + ], + 'SecondPlugin' => [ + 'queries' => $minQueriesTrigger, + 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES, + ] + ], + [], + ] + ], + 2 + ] + ]; + } + + /** + * @dataProvider dataTest + */ + public function test(array $queries, $expectedLogCalls): void { + $this->plugin->initialize($this->server); + $this->server->expects($this->once())->method('getPluginQueries') + ->willReturn($queries); + + $this->server->expects(empty($queries) ? $this->never() : $this->once()) + ->method('getLogger') + ->willReturn($this->logger); + + $this->logger->expects($this->exactly($expectedLogCalls))->method('error'); + $this->plugin->afterResponse($this->request, $this->response); + } + + protected function setUp(): void { + parent::setUp(); + + $this->plugin = new PropFindMonitorPlugin(); + $this->server = $this->createMock(Server::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->request = $this->createMock(Request::class); + $this->response = $this->createMock(Response::class); + } +} diff --git a/apps/dav/tests/unit/Connector/Sabre/PropFindPreloadNotifyPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/PropFindPreloadNotifyPluginTest.php new file mode 100644 index 00000000000..52fe3eba5bf --- /dev/null +++ b/apps/dav/tests/unit/Connector/Sabre/PropFindPreloadNotifyPluginTest.php @@ -0,0 +1,92 @@ +<?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\Connector\Sabre; + +use OCA\DAV\Connector\Sabre\PropFindPreloadNotifyPlugin; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\MockObject\MockObject; +use Sabre\DAV\ICollection; +use Sabre\DAV\IFile; +use Sabre\DAV\PropFind; +use Sabre\DAV\Server; +use Test\TestCase; + +class PropFindPreloadNotifyPluginTest extends TestCase { + + private Server&MockObject $server; + private PropFindPreloadNotifyPlugin $plugin; + + protected function setUp(): void { + parent::setUp(); + + $this->server = $this->createMock(Server::class); + $this->plugin = new PropFindPreloadNotifyPlugin(); + } + + public function testInitialize(): void { + $this->server + ->expects(self::once()) + ->method('on') + ->with('propFind', + $this->anything(), 1); + $this->plugin->initialize($this->server); + } + + public static function dataTestCollectionPreloadNotifier(): array { + return [ + 'When node is not a collection, should not emit' => [ + IFile::class, + 1, + false, + true + ], + 'When node is a collection but depth is zero, should not emit' => [ + ICollection::class, + 0, + false, + true + ], + 'When node is a collection, and depth > 0, should emit' => [ + ICollection::class, + 1, + true, + true + ], + 'When node is a collection, and depth is infinite, should emit' + => [ + ICollection::class, + Server::DEPTH_INFINITY, + true, + true + ], + 'When called called handler returns false, it should be returned' + => [ + ICollection::class, + 1, + true, + false + ] + ]; + } + + #[DataProvider(methodName: 'dataTestCollectionPreloadNotifier')] + public function testCollectionPreloadNotifier(string $nodeType, int $depth, bool $shouldEmit, bool $emitReturns): + void { + $this->plugin->initialize($this->server); + $propFind = $this->createMock(PropFind::class); + $propFind->expects(self::any())->method('getDepth')->willReturn($depth); + $node = $this->createMock($nodeType); + + $expectation = $shouldEmit ? self::once() : self::never(); + $this->server->expects($expectation)->method('emit')->with('preloadCollection', + [$propFind, $node])->willReturn($emitReturns); + $return = $this->plugin->collectionPreloadNotifier($propFind, $node); + $this->assertEquals($emitReturns, $return); + } +} diff --git a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php index 1c8e29dab38..33f579eb913 100644 --- a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php @@ -223,6 +223,7 @@ class SharesPluginTest extends \Test\TestCase { 0 ); + $this->server->emit('preloadCollection', [$propFindRoot, $sabreNode]); $this->plugin->handleGetProperties( $propFindRoot, $sabreNode diff --git a/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php index 5003280bfdc..554a4a1424e 100644 --- a/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php @@ -147,6 +147,8 @@ class TagsPluginTest extends \Test\TestCase { 0 ); + $this->server->emit('preloadCollection', [$propFindRoot, $node]); + $this->plugin->handleGetProperties( $propFindRoot, $node diff --git a/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php b/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php index 2a85c0cbecd..517969fc9a3 100644 --- a/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php +++ b/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php @@ -10,6 +10,7 @@ namespace OCA\DAV\Tests\unit\DAV; use OCA\DAV\CalDAV\Calendar; use OCA\DAV\CalDAV\DefaultCalendarValidator; use OCA\DAV\DAV\CustomPropertiesBackend; +use OCA\DAV\Db\PropertyMapper; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; use OCP\IUser; @@ -36,6 +37,7 @@ class CustomPropertiesBackendTest extends TestCase { private IUser&MockObject $user; private DefaultCalendarValidator&MockObject $defaultCalendarValidator; private CustomPropertiesBackend $backend; + private PropertyMapper $propertyMapper; protected function setUp(): void { parent::setUp(); @@ -49,6 +51,7 @@ class CustomPropertiesBackendTest extends TestCase { ->with() ->willReturn('dummy_user_42'); $this->dbConnection = \OCP\Server::get(IDBConnection::class); + $this->propertyMapper = \OCP\Server::get(PropertyMapper::class); $this->defaultCalendarValidator = $this->createMock(DefaultCalendarValidator::class); $this->backend = new CustomPropertiesBackend( @@ -56,6 +59,7 @@ class CustomPropertiesBackendTest extends TestCase { $this->tree, $this->dbConnection, $this->user, + $this->propertyMapper, $this->defaultCalendarValidator, ); } @@ -129,6 +133,7 @@ class CustomPropertiesBackendTest extends TestCase { $this->tree, $db, $this->user, + $this->propertyMapper, $this->defaultCalendarValidator, ); |