From 241c22df1a8f0dec517bcc16e008c90dfd24c953 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 3 Oct 2024 18:05:43 +0200 Subject: [PATCH] test: add some minimal testing for metadata storage Signed-off-by: Robin Appelman --- .../FilesMetadata/FilesMetadataManager.php | 4 +- .../FilesMetadata/Model/FilesMetadata.php | 10 +- .../Service/MetadataRequestService.php | 7 +- .../FilesMetadataManagerTest.php | 98 +++++++++++++++++++ 4 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 tests/lib/FilesMetadata/FilesMetadataManagerTest.php diff --git a/lib/private/FilesMetadata/FilesMetadataManager.php b/lib/private/FilesMetadata/FilesMetadataManager.php index b0a08c4f119cd..4846799b3d46c 100644 --- a/lib/private/FilesMetadata/FilesMetadataManager.php +++ b/lib/private/FilesMetadata/FilesMetadataManager.php @@ -81,10 +81,10 @@ public function refreshMetadata( try { /** @var FilesMetadata $metadata */ $metadata = $this->metadataRequestService->getMetadataFromFileId($node->getId()); - $metadata->setStorageId($storageId); } catch (FilesMetadataNotFoundException) { - $metadata = new FilesMetadata($node->getId(), $storageId); + $metadata = new FilesMetadata($node->getId()); } + $metadata->setStorageId($storageId); // if $process is LIVE, we enforce LIVE // if $process is NAMED, we go NAMED diff --git a/lib/private/FilesMetadata/Model/FilesMetadata.php b/lib/private/FilesMetadata/Model/FilesMetadata.php index d35e4a375e3a1..b66e1fe371110 100644 --- a/lib/private/FilesMetadata/Model/FilesMetadata.php +++ b/lib/private/FilesMetadata/Model/FilesMetadata.php @@ -27,10 +27,10 @@ class FilesMetadata implements IFilesMetadata { private bool $updated = false; private int $lastUpdate = 0; private string $syncToken = ''; + private ?int $storageId = null; public function __construct( private int $fileId = 0, - private ?int $storageId = null, ) { } @@ -47,6 +47,14 @@ public function getStorageId(): ?int { return $this->storageId; } + /** + * Set which storage the file this metadata belongs to. + * + * This helps with sharded filecache setups to know where to store the metadata + * + * @param int $storageId + * @return void + */ public function setStorageId(int $storageId): void { $this->storageId = $storageId; } diff --git a/lib/private/FilesMetadata/Service/MetadataRequestService.php b/lib/private/FilesMetadata/Service/MetadataRequestService.php index 880014a598c3c..2fb63887a8754 100644 --- a/lib/private/FilesMetadata/Service/MetadataRequestService.php +++ b/lib/private/FilesMetadata/Service/MetadataRequestService.php @@ -29,8 +29,11 @@ public function __construct( } private function getStorageId(IFilesMetadata $filesMetadata): int { - if ($filesMetadata instanceof FilesMetadata && $filesMetadata->getStorageId()) { - return $filesMetadata->getStorageId(); + if ($filesMetadata instanceof FilesMetadata) { + $storage = $filesMetadata->getStorageId(); + if ($storage) { + return $storage; + } } // all code paths that lead to saving metadata *should* have the storage id set // this fallback is there just in case diff --git a/tests/lib/FilesMetadata/FilesMetadataManagerTest.php b/tests/lib/FilesMetadata/FilesMetadataManagerTest.php new file mode 100644 index 0000000000000..f005b283c9087 --- /dev/null +++ b/tests/lib/FilesMetadata/FilesMetadataManagerTest.php @@ -0,0 +1,98 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace Test\FilesMetadata; + +use OC\BackgroundJob\JobList; +use OC\Files\Storage\Temporary; +use OC\FilesMetadata\FilesMetadataManager; +use OC\FilesMetadata\Service\IndexRequestService; +use OC\FilesMetadata\Service\MetadataRequestService; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\FilesMetadata\AMetadataEvent; +use OCP\IAppConfig; +use OCP\IDBConnection; +use OCP\Server; +use Psr\Log\LoggerInterface; +use Test\TestCase; +use Test\Traits\MountProviderTrait; +use Test\Traits\UserTrait; + +/** + * @group DB + */ +class FilesMetadataManagerTest extends TestCase { + use UserTrait; + use MountProviderTrait; + + private IEventDispatcher $eventDispatcher; + private JobList $jobList; + private IAppConfig $appConfig; + private LoggerInterface $logger; + private MetadataRequestService $metadataRequestService; + private IndexRequestService $indexRequestService; + private FilesMetadataManager $manager; + private IDBConnection $connection; + private Folder $userFolder; + private array $metadata = []; + + protected function setUp(): void { + parent::setUp(); + + $this->jobList = $this->createMock(JobList::class); + $this->eventDispatcher = $this->createMock(IEventDispatcher::class); + $this->eventDispatcher->method('dispatchTyped')->willReturnCallback(function(Event $event) { + if ($event instanceof AMetadataEvent) { + $name = $event->getNode()->getName(); + if (isset($this->metadata[$name])) { + $meta = $event->getMetadata(); + foreach ($this->metadata[$name] as $key => $value) { + $meta->setString($key, $value); + } + } + } + }); + $this->appConfig = $this->createMock(IAppConfig::class); + $this->logger = $this->createMock(LoggerInterface::class); + + $this->connection = Server::get(IDBConnection::class); + $this->metadataRequestService = new MetadataRequestService($this->connection, $this->logger); + $this->indexRequestService = new IndexRequestService($this->connection, $this->logger); + $this->manager = new FilesMetadataManager( + $this->eventDispatcher, + $this->jobList, + $this->appConfig, + $this->logger, + $this->metadataRequestService, + $this->indexRequestService, + ); + + $this->createUser('metatest', ''); + $this->registerMount('metatest', new Temporary([]), '/metatest'); + + $rootFolder = Server::get(IRootFolder::class); + $this->userFolder = $rootFolder->getUserFolder('metatest'); + } + + public function testRefreshMetadata(): void { + $this->metadata['test.txt'] = [ + 'istest' => 'yes' + ]; + $file = $this->userFolder->newFile('test.txt', 'test'); + $stored = $this->manager->refreshMetadata($file); + $this->assertEquals($file->getId(), $stored->getFileId()); + $this->assertEquals('yes', $stored->getString('istest')); + + $retrieved = $this->manager->getMetadata($file->getId()); + $this->assertEquals($file->getId(), $retrieved->getFileId()); + $this->assertEquals('yes', $retrieved->getString('istest')); + } +}