]> source.dussan.org Git - nextcloud-server.git/commitdiff
test(sharing): Add unit tests proofing the chunking perf/noid/split-getSharedWith-query-into-more-performance-sets 43481/head
authorJoas Schilling <coding@schilljs.com>
Fri, 9 Feb 2024 13:38:42 +0000 (14:38 +0100)
committerJoas Schilling <coding@schilljs.com>
Fri, 9 Feb 2024 13:38:42 +0000 (14:38 +0100)
Signed-off-by: Joas Schilling <coding@schilljs.com>
lib/private/Share20/DefaultShareProvider.php
tests/lib/Share20/DefaultShareProviderTest.php

index a82aba056ea29c2c5c1efb7c191918f929d96b78..03880b4bba7b4d2d489845f780cd9e2b2d57e95a 100644 (file)
@@ -63,6 +63,8 @@ use function str_starts_with;
  * @package OC\Share20
  */
 class DefaultShareProvider implements IShareProvider {
+       protected int $chunkSize = 1000;
+
        // Special share type for user modified group shares
        public const SHARE_TYPE_USERGROUP = 2;
 
@@ -1095,7 +1097,7 @@ class DefaultShareProvider implements IShareProvider {
                        ->where($queryFileCache->expr()->in('f.fileid', $queryFileCache->createParameter('fileIds')));
 
                $allFileIds = array_keys($fileData);
-               foreach (array_chunk($allFileIds, 1000) as $fileIds) {
+               foreach (array_chunk($allFileIds, $this->chunkSize) as $fileIds) {
                        // Filecache and storage info
                        $queryFileCache->setParameter('fileIds', $fileIds, IQueryBuilder::PARAM_INT_ARRAY);
 
@@ -1145,7 +1147,7 @@ class DefaultShareProvider implements IShareProvider {
                /** @var array<int, ?array> $fileData */
                $fileData = [];
 
-               foreach (array_chunk($allGroups, 1000) as $groups) {
+               foreach (array_chunk($allGroups, $this->chunkSize) as $groups) {
                        $query->setParameter('groups', $groups, IQueryBuilder::PARAM_STR_ARRAY);
 
                        $result = $query->executeQuery();
@@ -1158,6 +1160,7 @@ class DefaultShareProvider implements IShareProvider {
                                $fileData[(int)$row['file_source']] = null;
                        }
                        $result->closeCursor();
+
                }
 
                if (empty($fileData)) {
@@ -1174,7 +1177,7 @@ class DefaultShareProvider implements IShareProvider {
                        ->where($queryFileCache->expr()->in('f.fileid', $queryFileCache->createParameter('fileIds')));
 
                $allFileIds = array_keys($fileData);
-               foreach (array_chunk($allFileIds, 1000) as $fileIds) {
+               foreach (array_chunk($allFileIds, $this->chunkSize) as $fileIds) {
                        // Filecache and storage info
                        $queryFileCache->setParameter('fileIds', $fileIds, IQueryBuilder::PARAM_INT_ARRAY);
 
index f977619b7b246763e486ba609e6620d96744ee51..0dca507eae46d11d0e3ce9415aa7413e8d1c0415 100644 (file)
@@ -994,6 +994,130 @@ class DefaultShareProviderTest extends \Test\TestCase {
                $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
        }
 
+       public function testGetAllSharedWithUser(): void {
+               $storageId = $this->createTestStorageEntry('home::shareOwner');
+               $fileIds = [];
+               for ($i = 0; $i < 50; $i++) {
+                       $fileIds[] = $this->createTestFileEntry('files/test-' . $i . '.txt', $storageId);
+               }
+
+               $shareIds = [];
+               foreach ($fileIds as $fileId) {
+                       $qb = $this->dbConn->getQueryBuilder();
+                       $qb->insert('share')
+                               ->values([
+                                       'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
+                                       'share_with' => $qb->expr()->literal('sharedWith'),
+                                       'uid_owner' => $qb->expr()->literal('shareOwner'),
+                                       'uid_initiator' => $qb->expr()->literal('sharedBy'),
+                                       'item_type' => $qb->expr()->literal('file'),
+                                       'file_source' => $qb->expr()->literal($fileId),
+                                       'file_target' => $qb->expr()->literal('myTarget'),
+                                       'permissions' => $qb->expr()->literal(13),
+                               ]);
+                       $qb->executeStatement();
+                       $shareIds[$fileId] = $qb->getLastInsertId();
+               }
+
+               $file = $this->createMock(File::class);
+               $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
+               $this->rootFolder->method('getById')->willReturn([$file]);
+
+               self::invokePrivate($this->provider, 'chunkSize', [5]);
+               $shares = $this->provider->getSharedWith('sharedWith', IShare::TYPE_USER, null, -1, 0);
+               $this->assertCount(50, $shares);
+
+               foreach ($shares as $share) {
+                       $this->assertEquals($shareIds[$share->getNodeId()], $share->getId());
+                       $this->assertEquals('sharedWith', $share->getSharedWith());
+                       $this->assertEquals('shareOwner', $share->getShareOwner());
+                       $this->assertEquals('sharedBy', $share->getSharedBy());
+                       $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
+               }
+       }
+       public function testGetAllSharedWithGroup() {
+               $storageId = $this->createTestStorageEntry('home::shareOwner');
+               $fileIds = [];
+               for ($i = 0; $i < 50; $i++) {
+                       $fileIds[] = $this->createTestFileEntry('files/test-' . $i . '.txt', $storageId);
+               }
+
+               $shareIdToFileIds = [];
+               $shareIdToGroupId = [];
+               for ($i = 0; $i < 50; $i++) {
+                       $qb = $this->dbConn->getQueryBuilder();
+                       $qb->insert('share')
+                               ->values([
+                                       'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
+                                       'share_with' => $qb->expr()->literal('sharedWith'),
+                                       'uid_owner' => $qb->expr()->literal('shareOwner'),
+                                       'uid_initiator' => $qb->expr()->literal('sharedBy'),
+                                       'item_type' => $qb->expr()->literal('file'),
+                                       'file_source' => $qb->expr()->literal($fileIds[$i]),
+                                       'file_target' => $qb->expr()->literal('myTarget' . $i . 'shareWith'),
+                                       'permissions' => $qb->expr()->literal(13),
+                               ]);
+                       $qb->executeStatement();
+                       $shareId = $qb->getLastInsertId();
+                       $shareIdToFileIds[$shareId] = $fileIds[$i];
+                       $shareIdToGroupId[$shareId] = 'sharedWith';
+
+                       $qb = $this->dbConn->getQueryBuilder();
+                       $qb->insert('share')
+                               ->values([
+                                       'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
+                                       'share_with' => $qb->expr()->literal('group' . $i),
+                                       'uid_owner' => $qb->expr()->literal('shareOwner'),
+                                       'uid_initiator' => $qb->expr()->literal('sharedBy'),
+                                       'item_type' => $qb->expr()->literal('file'),
+                                       'file_source' => $qb->expr()->literal($fileIds[$i]),
+                                       'file_target' => $qb->expr()->literal('myTarget' . $i . 'group'),
+                                       'permissions' => $qb->expr()->literal(13),
+                               ]);
+                       $qb->executeStatement();
+                       $shareId = $qb->getLastInsertId();
+                       $shareIdToFileIds[$shareId] = $fileIds[$i];
+                       $shareIdToGroupId[$shareId] = 'group' . $i;
+               }
+
+               $groups = [];
+               foreach (range(0, 100) as $i) {
+                       $groups[] = 'group'.$i;
+               }
+
+               $groups[] = 'sharedWith';
+
+               $user = $this->createMock(IUser::class);
+               $user->method('getUID')->willReturn('sharedWith');
+               $owner = $this->createMock(IUser::class);
+               $owner->method('getUID')->willReturn('shareOwner');
+               $initiator = $this->createMock(IUser::class);
+               $initiator->method('getUID')->willReturn('sharedBy');
+
+               $this->userManager->method('get')->willReturnMap([
+                       ['sharedWith', $user],
+                       ['shareOwner', $owner],
+                       ['sharedBy', $initiator],
+               ]);
+               $this->groupManager->method('getUserGroupIds')->with($user)->willReturn($groups);
+
+               $file = $this->createMock(File::class);
+               $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
+               $this->rootFolder->method('getById')->willReturn([$file]);
+
+               self::invokePrivate($this->provider, 'chunkSize', [5]);
+               $shares = $this->provider->getSharedWith('sharedWith', IShare::TYPE_GROUP, null, -1, 0);
+               $this->assertCount(100, $shares);
+
+               foreach ($shares as $share) {
+                       $this->assertEquals($shareIdToFileIds[$share->getId()], $share->getNodeId());
+                       $this->assertEquals($shareIdToGroupId[$share->getId()], $share->getSharedWith());
+                       $this->assertEquals('shareOwner', $share->getShareOwner());
+                       $this->assertEquals('sharedBy', $share->getSharedBy());
+                       $this->assertEquals(IShare::TYPE_GROUP, $share->getShareType());
+               }
+       }
+
        /**
         * @dataProvider storageAndFileNameProvider
         */