diff options
Diffstat (limited to 'tests/lib/Files')
77 files changed, 4061 insertions, 2115 deletions
diff --git a/tests/lib/Files/AppData/AppDataTest.php b/tests/lib/Files/AppData/AppDataTest.php index 241e49a026f..ed006622504 100644 --- a/tests/lib/Files/AppData/AppDataTest.php +++ b/tests/lib/Files/AppData/AppDataTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -49,7 +50,7 @@ class AppDataTest extends \Test\TestCase { return $appFolder; } - public function testGetFolder() { + public function testGetFolder(): void { $folder = $this->createMock(Folder::class); $this->rootFolder->expects($this->once()) @@ -61,7 +62,7 @@ class AppDataTest extends \Test\TestCase { $this->assertInstanceOf(ISimpleFolder::class, $result); } - public function testNewFolder() { + public function testNewFolder(): void { $appFolder = $this->setupAppFolder(); $folder = $this->createMock(Folder::class); @@ -75,7 +76,7 @@ class AppDataTest extends \Test\TestCase { $this->assertInstanceOf(ISimpleFolder::class, $result); } - public function testGetDirectoryListing() { + public function testGetDirectoryListing(): void { $appFolder = $this->setupAppFolder(); $file = $this->createMock(File::class); diff --git a/tests/lib/Files/AppData/FactoryTest.php b/tests/lib/Files/AppData/FactoryTest.php index 1aad461e633..6092c931091 100644 --- a/tests/lib/Files/AppData/FactoryTest.php +++ b/tests/lib/Files/AppData/FactoryTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -28,7 +29,7 @@ class FactoryTest extends \Test\TestCase { $this->factory = new Factory($this->rootFolder, $this->systemConfig); } - public function testGet() { + public function testGet(): void { $this->rootFolder->expects($this->never()) ->method($this->anything()); $this->systemConfig->expects($this->never()) diff --git a/tests/lib/Files/Cache/CacheTest.php b/tests/lib/Files/Cache/CacheTest.php index faecbf54491..383962b7224 100644 --- a/tests/lib/Files/Cache/CacheTest.php +++ b/tests/lib/Files/Cache/CacheTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,16 +8,23 @@ namespace Test\Files\Cache; -use Doctrine\DBAL\Platforms\MySqlPlatform; use OC\Files\Cache\Cache; +use OC\Files\Cache\CacheEntry; use OC\Files\Search\SearchComparison; use OC\Files\Search\SearchQuery; +use OC\Files\Storage\Temporary; +use OC\User\User; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Cache\ICacheEntry; use OCP\Files\Search\ISearchComparison; +use OCP\IDBConnection; +use OCP\ITagManager; use OCP\IUser; +use OCP\IUserManager; +use OCP\Server; -class LongId extends \OC\Files\Storage\Temporary { - public function getId() { +class LongId extends Temporary { + public function getId(): string { return 'long:' . str_repeat('foo', 50) . parent::getId(); } } @@ -30,28 +38,47 @@ class LongId extends \OC\Files\Storage\Temporary { */ class CacheTest extends \Test\TestCase { /** - * @var \OC\Files\Storage\Temporary $storage ; + * @var Temporary $storage ; */ protected $storage; /** - * @var \OC\Files\Storage\Temporary $storage2 ; + * @var Temporary $storage2 ; */ protected $storage2; /** - * @var \OC\Files\Cache\Cache $cache + * @var Cache $cache */ protected $cache; /** - * @var \OC\Files\Cache\Cache $cache2 + * @var Cache $cache2 */ protected $cache2; - public function testGetNumericId() { + protected function setUp(): void { + parent::setUp(); + + $this->storage = new Temporary([]); + $this->storage2 = new Temporary([]); + $this->cache = new Cache($this->storage); + $this->cache2 = new Cache($this->storage2); + $this->cache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); + $this->cache2->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); + } + + protected function tearDown(): void { + if ($this->cache) { + $this->cache->clear(); + } + + parent::tearDown(); + } + + public function testGetNumericId(): void { $this->assertNotNull($this->cache->getNumericStorageId()); } - public function testSimple() { + public function testSimple(): void { $file1 = 'foo'; $file2 = 'foo/bar'; $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder']; @@ -97,7 +124,7 @@ class CacheTest extends \Test\TestCase { $this->assertEquals($cacheData1, $this->cache->get($id1)); } - public function testCacheEntryGetters() { + public function testCacheEntryGetters(): void { $file1 = 'foo'; $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/file']; @@ -122,33 +149,31 @@ class CacheTest extends \Test\TestCase { $this->assertEquals($entry->getUnencryptedSize(), 100); } - public function testPartial() { + public function testPartial(): void { $file1 = 'foo'; $this->cache->put($file1, ['size' => 10]); - $this->assertEquals(['size' => 10], $this->cache->get($file1)); + $this->assertEquals(new CacheEntry(['size' => 10]), $this->cache->get($file1)); $this->cache->put($file1, ['mtime' => 15]); - $this->assertEquals(['size' => 10, 'mtime' => 15], $this->cache->get($file1)); + $this->assertEquals(new CacheEntry(['size' => 10, 'mtime' => 15]), $this->cache->get($file1)); $this->cache->put($file1, ['size' => 12]); - $this->assertEquals(['size' => 12, 'mtime' => 15], $this->cache->get($file1)); + $this->assertEquals(new CacheEntry(['size' => 12, 'mtime' => 15]), $this->cache->get($file1)); } - /** - * @dataProvider folderDataProvider - */ - public function testFolder($folder) { + #[\PHPUnit\Framework\Attributes\DataProvider('folderDataProvider')] + public function testFolder($folder): void { if (strpos($folder, 'F09F9890')) { // 4 byte UTF doesn't work on mysql - $params = \OC::$server->get(\OC\DB\Connection::class)->getParams(); - if (\OC::$server->getDatabaseConnection()->getDatabasePlatform() instanceof MySqlPlatform && $params['charset'] !== 'utf8mb4') { + $params = Server::get(\OC\DB\Connection::class)->getParams(); + if (Server::get(IDBConnection::class)->getDatabaseProvider() === IDBConnection::PLATFORM_MYSQL && $params['charset'] !== 'utf8mb4') { $this->markTestSkipped('MySQL doesn\'t support 4 byte UTF-8'); } } $file2 = $folder . '/bar'; $file3 = $folder . '/foo'; - $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; + $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; $fileData = []; $fileData['bar'] = ['size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file']; $fileData['foo'] = ['size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file']; @@ -187,8 +212,8 @@ class CacheTest extends \Test\TestCase { $this->assertFalse($this->cache->inCache($folder . '/bar')); } - public function testRemoveRecursive() { - $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; + public function testRemoveRecursive(): void { + $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; $fileData = ['size' => 1000, 'mtime' => 20, 'mimetype' => 'text/plain']; $folders = ['folder', 'folder/subfolder', 'folder/sub2', 'folder/sub2/sub3']; $files = ['folder/foo.txt', 'folder/bar.txt', 'folder/subfolder/asd.txt', 'folder/sub2/qwerty.txt', 'folder/sub2/sub3/foo.txt']; @@ -206,7 +231,7 @@ class CacheTest extends \Test\TestCase { } } - public function folderDataProvider() { + public static function folderDataProvider(): array { return [ ['folder'], // that was too easy, try something harder @@ -220,11 +245,11 @@ class CacheTest extends \Test\TestCase { ]; } - public function testEncryptedFolder() { + public function testEncryptedFolder(): void { $file1 = 'folder'; $file2 = 'folder/bar'; $file3 = 'folder/foo'; - $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; + $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; $fileData = []; $fileData['bar'] = ['size' => 1000, 'encrypted' => 1, 'mtime' => 20, 'mimetype' => 'foo/file']; $fileData['foo'] = ['size' => 20, 'encrypted' => 1, 'mtime' => 25, 'mimetype' => 'foo/file']; @@ -263,15 +288,14 @@ class CacheTest extends \Test\TestCase { $this->assertFalse($this->cache->inCache('folder/bar')); } - public function testRootFolderSizeForNonHomeStorage() { + public function testRootFolderSizeForNonHomeStorage(): void { $dir1 = 'knownsize'; $dir2 = 'unknownsize'; $fileData = []; - $fileData[''] = ['size' => -1, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory']; - $fileData[$dir1] = ['size' => 1000, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory']; - $fileData[$dir2] = ['size' => -1, 'mtime' => 25, 'mimetype' => 'httpd/unix-directory']; + $fileData[''] = ['size' => -1, 'mtime' => 20, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; + $fileData[$dir1] = ['size' => 1000, 'mtime' => 20, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; + $fileData[$dir2] = ['size' => -1, 'mtime' => 25, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; - $this->cache->put('', $fileData['']); $this->cache->put($dir1, $fileData[$dir1]); $this->cache->put($dir2, $fileData[$dir2]); @@ -290,17 +314,17 @@ class CacheTest extends \Test\TestCase { $this->assertFalse($this->cache->inCache($dir2)); } - public function testStatus() { - $this->assertEquals(\OC\Files\Cache\Cache::NOT_FOUND, $this->cache->getStatus('foo')); + public function testStatus(): void { + $this->assertEquals(Cache::NOT_FOUND, $this->cache->getStatus('foo')); $this->cache->put('foo', ['size' => -1]); - $this->assertEquals(\OC\Files\Cache\Cache::PARTIAL, $this->cache->getStatus('foo')); + $this->assertEquals(Cache::PARTIAL, $this->cache->getStatus('foo')); $this->cache->put('foo', ['size' => -1, 'mtime' => 20, 'mimetype' => 'foo/file']); - $this->assertEquals(\OC\Files\Cache\Cache::SHALLOW, $this->cache->getStatus('foo')); + $this->assertEquals(Cache::SHALLOW, $this->cache->getStatus('foo')); $this->cache->put('foo', ['size' => 10]); - $this->assertEquals(\OC\Files\Cache\Cache::COMPLETE, $this->cache->getStatus('foo')); + $this->assertEquals(Cache::COMPLETE, $this->cache->getStatus('foo')); } - public function putWithAllKindOfQuotesData() { + public static function putWithAllKindOfQuotesData(): array { return [ ['`backtick`'], ['´forward´'], @@ -309,11 +333,11 @@ class CacheTest extends \Test\TestCase { } /** - * @dataProvider putWithAllKindOfQuotesData * @param $fileName */ - public function testPutWithAllKindOfQuotes($fileName) { - $this->assertEquals(\OC\Files\Cache\Cache::NOT_FOUND, $this->cache->get($fileName)); + #[\PHPUnit\Framework\Attributes\DataProvider('putWithAllKindOfQuotesData')] + public function testPutWithAllKindOfQuotes($fileName): void { + $this->assertEquals(Cache::NOT_FOUND, $this->cache->get($fileName)); $this->cache->put($fileName, ['size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file', 'etag' => $fileName]); $cacheEntry = $this->cache->get($fileName); @@ -321,7 +345,7 @@ class CacheTest extends \Test\TestCase { $this->assertEquals($fileName, $cacheEntry['path']); } - public function testSearch() { + public function testSearch(): void { $file1 = 'folder'; $file2 = 'folder/foobar'; $file3 = 'folder/foo'; @@ -338,7 +362,6 @@ class CacheTest extends \Test\TestCase { $this->assertEquals(1, count($this->cache->search('foo'))); $this->assertEquals(1, count($this->cache->search('%folder%'))); $this->assertEquals(1, count($this->cache->search('folder%'))); - $this->assertEquals(3, count($this->cache->search('%'))); // case insensitive search should match the same files $this->assertEquals(2, count($this->cache->search('%Foo%'))); @@ -350,11 +373,11 @@ class CacheTest extends \Test\TestCase { $this->assertEquals(2, count($this->cache->searchByMime('foo/file'))); } - public function testSearchQueryByTag() { + public function testSearchQueryByTag(): void { $userId = static::getUniqueID('user'); - \OC::$server->getUserManager()->createUser($userId, $userId); + Server::get(IUserManager::class)->createUser($userId, $userId); static::loginAsUser($userId); - $user = new \OC\User\User($userId, null, \OC::$server->get(IEventDispatcher::class)); + $user = new User($userId, null, Server::get(IEventDispatcher::class)); $file1 = 'folder'; $file2 = 'folder/foobar'; @@ -374,7 +397,7 @@ class CacheTest extends \Test\TestCase { $id4 = $this->cache->put($file4, $fileData['foo2']); $id5 = $this->cache->put($file5, $fileData['foo3']); - $tagManager = \OC::$server->getTagManager()->load('files', [], false, $userId); + $tagManager = Server::get(ITagManager::class)->load('files', [], false, $userId); $this->assertTrue($tagManager->tagAs($id1, 'tag1')); $this->assertTrue($tagManager->tagAs($id1, 'tag2')); $this->assertTrue($tagManager->tagAs($id2, 'tag2')); @@ -399,7 +422,7 @@ class CacheTest extends \Test\TestCase { $tagManager->delete('tag2'); static::logout(); - $user = \OC::$server->getUserManager()->get($userId); + $user = Server::get(IUserManager::class)->get($userId); if ($user !== null) { try { $user->delete(); @@ -408,7 +431,7 @@ class CacheTest extends \Test\TestCase { } } - public function testSearchByQuery() { + public function testSearchByQuery(): void { $file1 = 'folder'; $file2 = 'folder/foobar'; $file3 = 'folder/foo'; @@ -437,7 +460,7 @@ class CacheTest extends \Test\TestCase { new SearchComparison(ISearchComparison::COMPARE_GREATER_THAN_EQUAL, 'size', 100), 10, 0, [], $user))); } - public function movePathProvider() { + public static function movePathProvider(): array { return [ ['folder/foo', 'folder/foobar', ['1', '2']], ['folder/foo', 'foo', ['1', '2']], @@ -445,12 +468,10 @@ class CacheTest extends \Test\TestCase { ]; } - /** - * @dataProvider movePathProvider - */ - public function testMove($sourceFolder, $targetFolder, $children) { + #[\PHPUnit\Framework\Attributes\DataProvider('movePathProvider')] + public function testMove($sourceFolder, $targetFolder, $children): void { $data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/bar']; - $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; + $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; // create folders foreach ([$sourceFolder, $targetFolder] as $current) { @@ -483,7 +504,24 @@ class CacheTest extends \Test\TestCase { } } - public function testGetIncomplete() { + public function testMoveFromCache(): void { + $data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/bar']; + $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; + + $this->cache2->put('folder', $folderData); + $this->cache2->put('folder/sub', $data); + + + $this->cache->moveFromCache($this->cache2, 'folder', 'targetfolder'); + + $this->assertFalse($this->cache2->inCache('folder')); + $this->assertFalse($this->cache2->inCache('folder/sub')); + + $this->assertTrue($this->cache->inCache('targetfolder')); + $this->assertTrue($this->cache->inCache('targetfolder/sub')); + } + + public function testGetIncomplete(): void { $file1 = 'folder1'; $file2 = 'folder2'; $file3 = 'folder3'; @@ -500,13 +538,13 @@ class CacheTest extends \Test\TestCase { $this->assertEquals($file3, $this->cache->getIncomplete()); } - public function testNonExisting() { + public function testNonExisting(): void { $this->assertFalse($this->cache->get('foo.txt')); $this->assertFalse($this->cache->get(-1)); $this->assertEquals([], $this->cache->getFolderContents('foo')); } - public function testGetById() { + public function testGetById(): void { $storageId = $this->storage->getId(); $data = ['size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file']; $id = $this->cache->put('foo', $data); @@ -514,10 +552,10 @@ class CacheTest extends \Test\TestCase { if (strlen($storageId) > 64) { $storageId = md5($storageId); } - $this->assertEquals([$storageId, 'foo'], \OC\Files\Cache\Cache::getById($id)); + $this->assertEquals([$storageId, 'foo'], Cache::getById($id)); } - public function testStorageMTime() { + public function testStorageMTime(): void { $data = ['size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file']; $this->cache->put('foo', $data); $cachedData = $this->cache->get('foo'); @@ -534,19 +572,20 @@ class CacheTest extends \Test\TestCase { $this->assertEquals(25, $cachedData['mtime']); } - public function testLongId() { + public function testLongId(): void { $storage = new LongId([]); $cache = $storage->getCache(); + $cache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $storageId = $storage->getId(); $data = ['size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file']; $id = $cache->put('foo', $data); - $this->assertEquals([md5($storageId), 'foo'], \OC\Files\Cache\Cache::getById($id)); + $this->assertEquals([md5($storageId), 'foo'], Cache::getById($id)); } /** * this test show the bug resulting if we have no normalizer installed */ - public function testWithoutNormalizer() { + public function testWithoutNormalizer(): void { // folder name "Schön" with U+00F6 (normalized) $folderWith00F6 = "\x53\x63\x68\xc3\xb6\x6e"; @@ -554,10 +593,10 @@ class CacheTest extends \Test\TestCase { $folderWith0308 = "\x53\x63\x68\x6f\xcc\x88\x6e"; /** - * @var \OC\Files\Cache\Cache | \PHPUnit\Framework\MockObject\MockObject $cacheMock + * @var Cache|\PHPUnit\Framework\MockObject\MockObject $cacheMock */ $cacheMock = $this->getMockBuilder(Cache::class) - ->setMethods(['normalize']) + ->onlyMethods(['normalize']) ->setConstructorArgs([$this->storage]) ->getMock(); @@ -565,7 +604,7 @@ class CacheTest extends \Test\TestCase { ->method('normalize') ->willReturnArgument(0); - $data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; + $data = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; // put root folder $this->assertFalse($cacheMock->get('folder')); @@ -592,7 +631,7 @@ class CacheTest extends \Test\TestCase { /** * this test shows that there is no bug if we use the normalizer */ - public function testWithNormalizer() { + public function testWithNormalizer(): void { if (!class_exists('Patchwork\PHP\Shim\Normalizer')) { $this->markTestSkipped('The 3rdparty Normalizer extension is not available.'); return; @@ -604,7 +643,7 @@ class CacheTest extends \Test\TestCase { // folder name "Schön" with U+0308 (un-normalized) $folderWith0308 = "\x53\x63\x68\x6f\xcc\x88\x6e"; - $data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; + $data = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; // put root folder $this->assertFalse($this->cache->get('folder')); @@ -628,7 +667,7 @@ class CacheTest extends \Test\TestCase { $this->assertEquals(1, count($this->cache->getFolderContents('folder'))); } - public function bogusPathNamesProvider() { + public static function bogusPathNamesProvider(): array { return [ ['/bogus.txt', 'bogus.txt'], ['//bogus.txt', 'bogus.txt'], @@ -639,16 +678,11 @@ class CacheTest extends \Test\TestCase { /** * Test bogus paths with leading or doubled slashes - * - * @dataProvider bogusPathNamesProvider */ - public function testBogusPaths($bogusPath, $fixedBogusPath) { - $data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; - - // put root folder - $this->assertFalse($this->cache->get('')); - $parentId = $this->cache->put('', $data); - $this->assertGreaterThan(0, $parentId); + #[\PHPUnit\Framework\Attributes\DataProvider('bogusPathNamesProvider')] + public function testBogusPaths($bogusPath, $fixedBogusPath): void { + $data = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; + $parentId = $this->cache->getId(''); $this->assertGreaterThan(0, $this->cache->put($bogusPath, $data)); @@ -664,7 +698,7 @@ class CacheTest extends \Test\TestCase { $this->assertEquals($newData, $newDataFromBogus); } - public function testNoReuseOfFileId() { + public function testNoReuseOfFileId(): void { $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain']; $this->cache->put('somefile.txt', $data1); $info = $this->cache->get('somefile.txt'); @@ -677,7 +711,7 @@ class CacheTest extends \Test\TestCase { $this->assertNotEquals($fileId, $fileId2); } - public function escapingProvider() { + public static function escapingProvider(): array { return [ ['foo'], ['o%'], @@ -687,9 +721,9 @@ class CacheTest extends \Test\TestCase { /** * @param string $name - * @dataProvider escapingProvider */ - public function testEscaping($name) { + #[\PHPUnit\Framework\Attributes\DataProvider('escapingProvider')] + public function testEscaping($name): void { $data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain']; $this->cache->put($name, $data); $this->assertTrue($this->cache->inCache($name)); @@ -702,7 +736,7 @@ class CacheTest extends \Test\TestCase { $this->assertTrue($this->cache->inCache($name . 'asd')); $this->cache->remove($name . 'asd'); $this->assertFalse($this->cache->inCache($name . 'asd')); - $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; + $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; $this->cache->put($name, $folderData); $this->cache->put('other', $folderData); $childs = ['asd', 'bar', 'foo', 'sub/folder']; @@ -725,31 +759,30 @@ class CacheTest extends \Test\TestCase { } } - public function testExtended() { - $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; - $this->cache->put("", $folderData); + public function testExtended(): void { + $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; $data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain', 'creation_time' => 20]; - $id1 = $this->cache->put("foo1", $data); + $id1 = $this->cache->put('foo1', $data); $data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain', 'upload_time' => 30]; - $this->cache->put("foo2", $data); + $this->cache->put('foo2', $data); $data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain', 'metadata_etag' => 'foo']; - $this->cache->put("foo3", $data); + $this->cache->put('foo3', $data); $data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain']; - $id4 = $this->cache->put("foo4", $data); + $id4 = $this->cache->put('foo4', $data); $entry = $this->cache->get($id1); $this->assertEquals(20, $entry->getCreationTime()); $this->assertEquals(0, $entry->getUploadTime()); $this->assertEquals(null, $entry->getMetadataEtag()); - $entries = $this->cache->getFolderContents(""); + $entries = $this->cache->getFolderContents(''); $this->assertCount(4, $entries); - $this->assertEquals("foo1", $entries[0]->getName()); - $this->assertEquals("foo2", $entries[1]->getName()); - $this->assertEquals("foo3", $entries[2]->getName()); - $this->assertEquals("foo4", $entries[3]->getName()); + $this->assertEquals('foo1', $entries[0]->getName()); + $this->assertEquals('foo2', $entries[1]->getName()); + $this->assertEquals('foo3', $entries[2]->getName()); + $this->assertEquals('foo4', $entries[3]->getName()); $this->assertEquals(20, $entries[0]->getCreationTime()); $this->assertEquals(0, $entries[0]->getUploadTime()); @@ -774,11 +807,11 @@ class CacheTest extends \Test\TestCase { $this->assertEquals(25, $entry->getUploadTime()); $this->assertEquals(null, $entry->getMetadataEtag()); - $this->cache->put("sub", $folderData); + $this->cache->put('sub', $folderData); - $this->cache->move("foo1", "sub/foo1"); + $this->cache->move('foo1', 'sub/foo1'); - $entries = $this->cache->getFolderContents("sub"); + $entries = $this->cache->getFolderContents('sub'); $this->assertCount(1, $entries); $this->assertEquals(20, $entries[0]->getCreationTime()); @@ -792,23 +825,6 @@ class CacheTest extends \Test\TestCase { $this->assertEquals(25, $entry->getUploadTime()); $this->assertEquals(null, $entry->getMetadataEtag()); - $this->cache->remove("sub"); - } - - protected function tearDown(): void { - if ($this->cache) { - $this->cache->clear(); - } - - parent::tearDown(); - } - - protected function setUp(): void { - parent::setUp(); - - $this->storage = new \OC\Files\Storage\Temporary([]); - $this->storage2 = new \OC\Files\Storage\Temporary([]); - $this->cache = new \OC\Files\Cache\Cache($this->storage); - $this->cache2 = new \OC\Files\Cache\Cache($this->storage2); + $this->cache->remove('sub'); } } diff --git a/tests/lib/Files/Cache/FileAccessTest.php b/tests/lib/Files/Cache/FileAccessTest.php new file mode 100644 index 00000000000..59fa2494ea8 --- /dev/null +++ b/tests/lib/Files/Cache/FileAccessTest.php @@ -0,0 +1,438 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace Test\Files\Cache; + +use OC\Files\Cache\CacheEntry; +use OC\Files\Cache\FileAccess; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; +use Psr\Log\LoggerInterface; +use Test\TestCase; + +/** + * @group DB + */ +class FileAccessTest extends TestCase { + private IDBConnection $dbConnection; + private FileAccess $fileAccess; + + protected function setUp(): void { + parent::setUp(); + + // Setup the actual database connection (assume the database is configured properly in PHPUnit setup) + $this->dbConnection = \OCP\Server::get(IDBConnection::class); + + // Ensure FileAccess is instantiated with the real connection + $this->fileAccess = new FileAccess( + $this->dbConnection, + \OCP\Server::get(\OC\SystemConfig::class), + \OCP\Server::get(LoggerInterface::class), + \OCP\Server::get(\OC\FilesMetadata\FilesMetadataManager::class), + \OCP\Server::get(\OCP\Files\IMimeTypeLoader::class) + ); + + // Clear and prepare `filecache` table for tests + $queryBuilder = $this->dbConnection->getQueryBuilder()->runAcrossAllShards(); + $queryBuilder->delete('filecache')->executeStatement(); + + // Clean up potential leftovers from other tests + $queryBuilder = $this->dbConnection->getQueryBuilder(); + $queryBuilder->delete('mounts')->executeStatement(); + + + $this->setUpTestDatabaseForGetDistinctMounts(); + $this->setUpTestDatabaseForGetByAncestorInStorage(); + } + + private function setUpTestDatabaseForGetDistinctMounts(): void { + $queryBuilder = $this->dbConnection->getQueryBuilder(); + + // Insert test data + $queryBuilder->insert('mounts') + ->values([ + 'storage_id' => $queryBuilder->createNamedParameter(1, IQueryBuilder::PARAM_INT), + 'root_id' => $queryBuilder->createNamedParameter(10, IQueryBuilder::PARAM_INT), + 'mount_provider_class' => $queryBuilder->createNamedParameter('TestProviderClass1'), + 'mount_point' => $queryBuilder->createNamedParameter('/files'), + 'user_id' => $queryBuilder->createNamedParameter('test'), + ]) + ->executeStatement(); + + $queryBuilder->insert('mounts') + ->values([ + 'storage_id' => $queryBuilder->createNamedParameter(3, IQueryBuilder::PARAM_INT), + 'root_id' => $queryBuilder->createNamedParameter(30, IQueryBuilder::PARAM_INT), + 'mount_provider_class' => $queryBuilder->createNamedParameter('TestProviderClass1'), + 'mount_point' => $queryBuilder->createNamedParameter('/documents'), + 'user_id' => $queryBuilder->createNamedParameter('test'), + ]) + ->executeStatement(); + + $queryBuilder->insert('mounts') + ->values([ + 'storage_id' => $queryBuilder->createNamedParameter(4, IQueryBuilder::PARAM_INT), + 'root_id' => $queryBuilder->createNamedParameter(31, IQueryBuilder::PARAM_INT), + 'mount_provider_class' => $queryBuilder->createNamedParameter('TestProviderClass2'), + 'mount_point' => $queryBuilder->createNamedParameter('/foobar'), + 'user_id' => $queryBuilder->createNamedParameter('test'), + ]) + ->executeStatement(); + } + + /** + * Test that getDistinctMounts returns all mounts without filters + */ + public function testGetDistinctMountsWithoutFilters(): void { + $result = iterator_to_array($this->fileAccess->getDistinctMounts([], false)); + + $this->assertCount(3, $result); + + $this->assertEquals([ + 'storage_id' => 1, + 'root_id' => 10, + 'overridden_root' => 10, + ], $result[0]); + + $this->assertEquals([ + 'storage_id' => 3, + 'root_id' => 30, + 'overridden_root' => 30, + ], $result[1]); + + $this->assertEquals([ + 'storage_id' => 4, + 'root_id' => 31, + 'overridden_root' => 31, + ], $result[2]); + } + + /** + * Test that getDistinctMounts applies filtering by mount providers + */ + public function testGetDistinctMountsWithMountProviderFilter(): void { + $result = iterator_to_array($this->fileAccess->getDistinctMounts(['TestProviderClass1'], false)); + + $this->assertCount(2, $result); + + $this->assertEquals([ + 'storage_id' => 1, + 'root_id' => 10, + 'overridden_root' => 10, + ], $result[0]); + + $this->assertEquals([ + 'storage_id' => 3, + 'root_id' => 30, + 'overridden_root' => 30, + ], $result[1]); + } + + /** + * Test that getDistinctMounts rewrites home directory paths + */ + public function testGetDistinctMountsWithRewriteHomeDirectories(): void { + // Add additional test data for a home directory mount + $queryBuilder = $this->dbConnection->getQueryBuilder(); + $queryBuilder->insert('mounts') + ->values([ + 'storage_id' => $queryBuilder->createNamedParameter(4, IQueryBuilder::PARAM_INT), + 'root_id' => $queryBuilder->createNamedParameter(40, IQueryBuilder::PARAM_INT), + 'mount_provider_class' => $queryBuilder->createNamedParameter(\OC\Files\Mount\LocalHomeMountProvider::class), + 'mount_point' => $queryBuilder->createNamedParameter('/home/user'), + 'user_id' => $queryBuilder->createNamedParameter('test'), + ]) + ->executeStatement(); + + // Add a mount that is mounted in the home directory + $queryBuilder = $this->dbConnection->getQueryBuilder(); + $queryBuilder->insert('mounts') + ->values([ + 'storage_id' => $queryBuilder->createNamedParameter(5, IQueryBuilder::PARAM_INT), + 'root_id' => $queryBuilder->createNamedParameter(41, IQueryBuilder::PARAM_INT), + 'mount_provider_class' => $queryBuilder->createNamedParameter('TestMountProvider3'), + 'mount_point' => $queryBuilder->createNamedParameter('/test/files/foobar'), + 'user_id' => $queryBuilder->createNamedParameter('test'), + ]) + ->executeStatement(); + + // Simulate adding a "files" directory to the filecache table + $queryBuilder = $this->dbConnection->getQueryBuilder()->runAcrossAllShards(); + $queryBuilder->delete('filecache')->executeStatement(); + $queryBuilder = $this->dbConnection->getQueryBuilder(); + $queryBuilder->insert('filecache') + ->values([ + 'fileid' => $queryBuilder->createNamedParameter(99, IQueryBuilder::PARAM_INT), + 'storage' => $queryBuilder->createNamedParameter(4, IQueryBuilder::PARAM_INT), + 'parent' => $queryBuilder->createNamedParameter(40), + 'name' => $queryBuilder->createNamedParameter('files'), + 'path' => $queryBuilder->createNamedParameter('files'), + 'path_hash' => $queryBuilder->createNamedParameter(md5('files')), + ]) + ->executeStatement(); + + $result = iterator_to_array($this->fileAccess->getDistinctMounts()); + + $this->assertCount(2, $result); + + $this->assertEquals([ + 'storage_id' => 4, + 'root_id' => 40, + 'overridden_root' => 99, + ], $result[0]); + + $this->assertEquals([ + 'storage_id' => 5, + 'root_id' => 41, + 'overridden_root' => 41, + ], $result[1]); + } + + private function setUpTestDatabaseForGetByAncestorInStorage(): void { + // prepare `filecache` table for tests + $queryBuilder = $this->dbConnection->getQueryBuilder(); + + $queryBuilder->insert('filecache') + ->values([ + 'fileid' => 1, + 'parent' => 0, + 'path' => $queryBuilder->createNamedParameter('files'), + 'path_hash' => $queryBuilder->createNamedParameter(md5('files')), + 'storage' => $queryBuilder->createNamedParameter(1), + 'name' => $queryBuilder->createNamedParameter('files'), + 'mimetype' => 1, + 'encrypted' => 0, + ]) + ->executeStatement(); + + $queryBuilder->insert('filecache') + ->values([ + 'fileid' => 2, + 'parent' => 1, + 'path' => $queryBuilder->createNamedParameter('files/documents'), + 'path_hash' => $queryBuilder->createNamedParameter(md5('files/documents')), + 'storage' => $queryBuilder->createNamedParameter(1), + 'name' => $queryBuilder->createNamedParameter('documents'), + 'mimetype' => 2, + 'encrypted' => 1, + ]) + ->executeStatement(); + + $queryBuilder->insert('filecache') + ->values([ + 'fileid' => 3, + 'parent' => 1, + 'path' => $queryBuilder->createNamedParameter('files/photos'), + 'path_hash' => $queryBuilder->createNamedParameter(md5('files/photos')), + 'storage' => $queryBuilder->createNamedParameter(1), + 'name' => $queryBuilder->createNamedParameter('photos'), + 'mimetype' => 3, + 'encrypted' => 1, + ]) + ->executeStatement(); + + $queryBuilder->insert('filecache') + ->values([ + 'fileid' => 4, + 'parent' => 3, + 'path' => $queryBuilder->createNamedParameter('files/photos/endtoendencrypted'), + 'path_hash' => $queryBuilder->createNamedParameter(md5('files/photos/endtoendencrypted')), + 'storage' => $queryBuilder->createNamedParameter(1), + 'name' => $queryBuilder->createNamedParameter('endtoendencrypted'), + 'mimetype' => 4, + 'encrypted' => 0, + ]) + ->executeStatement(); + + $queryBuilder->insert('filecache') + ->values([ + 'fileid' => 5, + 'parent' => 1, + 'path' => $queryBuilder->createNamedParameter('files/serversideencrypted'), + 'path_hash' => $queryBuilder->createNamedParameter(md5('files/serversideencrypted')), + 'storage' => $queryBuilder->createNamedParameter(1), + 'name' => $queryBuilder->createNamedParameter('serversideencrypted'), + 'mimetype' => 4, + 'encrypted' => 1, + ]) + ->executeStatement(); + + $queryBuilder->insert('filecache') + ->values([ + 'fileid' => 6, + 'parent' => 0, + 'path' => $queryBuilder->createNamedParameter('files/storage2'), + 'path_hash' => $queryBuilder->createNamedParameter(md5('files/storage2')), + 'storage' => $queryBuilder->createNamedParameter(2), + 'name' => $queryBuilder->createNamedParameter('storage2'), + 'mimetype' => 5, + 'encrypted' => 0, + ]) + ->executeStatement(); + + $queryBuilder->insert('filecache') + ->values([ + 'fileid' => 7, + 'parent' => 6, + 'path' => $queryBuilder->createNamedParameter('files/storage2/file'), + 'path_hash' => $queryBuilder->createNamedParameter(md5('files/storage2/file')), + 'storage' => $queryBuilder->createNamedParameter(2), + 'name' => $queryBuilder->createNamedParameter('file'), + 'mimetype' => 6, + 'encrypted' => 0, + ]) + ->executeStatement(); + } + + /** + * Test fetching files by ancestor in storage. + */ + public function testGetByAncestorInStorage(): void { + $generator = $this->fileAccess->getByAncestorInStorage( + 1, // storageId + 1, // rootId + 0, // lastFileId + 10, // maxResults + [], // mimeTypes + true, // include end-to-end encrypted files + true, // include server-side encrypted files + ); + + $result = iterator_to_array($generator); + + $this->assertCount(4, $result); + + $paths = array_map(fn (CacheEntry $entry) => $entry->getPath(), $result); + $this->assertEquals([ + 'files/documents', + 'files/photos', + 'files/photos/endtoendencrypted', + 'files/serversideencrypted', + ], $paths); + } + + /** + * Test filtering by mime types. + */ + public function testGetByAncestorInStorageWithMimeTypes(): void { + $generator = $this->fileAccess->getByAncestorInStorage( + 1, + 1, + 0, + 10, + [2], // Only include documents (mimetype=2) + true, + true, + ); + + $result = iterator_to_array($generator); + + $this->assertCount(1, $result); + $this->assertEquals('files/documents', $result[0]->getPath()); + } + + /** + * Test excluding end-to-end encrypted files. + */ + public function testGetByAncestorInStorageWithoutEndToEndEncrypted(): void { + $generator = $this->fileAccess->getByAncestorInStorage( + 1, + 1, + 0, + 10, + [], + false, // exclude end-to-end encrypted files + true, + ); + + $result = iterator_to_array($generator); + + $this->assertCount(3, $result); + $paths = array_map(fn (CacheEntry $entry) => $entry->getPath(), $result); + $this->assertEquals(['files/documents', 'files/photos', 'files/serversideencrypted'], $paths); + } + + /** + * Test excluding server-side encrypted files. + */ + public function testGetByAncestorInStorageWithoutServerSideEncrypted(): void { + $generator = $this->fileAccess->getByAncestorInStorage( + 1, + 1, + 0, + 10, + [], + true, + false, // exclude server-side encrypted files + ); + + $result = iterator_to_array($generator); + + $this->assertCount(1, $result); + $this->assertEquals('files/photos/endtoendencrypted', $result[0]->getPath()); + } + + /** + * Test max result limits. + */ + public function testGetByAncestorInStorageWithMaxResults(): void { + $generator = $this->fileAccess->getByAncestorInStorage( + 1, + 1, + 0, + 1, // Limit to 1 result + [], + true, + true, + ); + + $result = iterator_to_array($generator); + + $this->assertCount(1, $result); + $this->assertEquals('files/documents', $result[0]->getPath()); + } + + /** + * Test rootId filter + */ + public function testGetByAncestorInStorageWithRootIdFilter(): void { + $generator = $this->fileAccess->getByAncestorInStorage( + 1, + 3, // Filter by rootId + 0, + 10, + [], + true, + true, + ); + + $result = iterator_to_array($generator); + + $this->assertCount(1, $result); + $this->assertEquals('files/photos/endtoendencrypted', $result[0]->getPath()); + } + + /** + * Test rootId filter + */ + public function testGetByAncestorInStorageWithStorageFilter(): void { + $generator = $this->fileAccess->getByAncestorInStorage( + 2, // Filter by storage + 6, // and by rootId + 0, + 10, + [], + true, + true, + ); + + $result = iterator_to_array($generator); + + $this->assertCount(1, $result); + $this->assertEquals('files/storage2/file', $result[0]->getPath()); + } +} diff --git a/tests/lib/Files/Cache/HomeCacheTest.php b/tests/lib/Files/Cache/HomeCacheTest.php index 986d6df4c17..86fda615fd7 100644 --- a/tests/lib/Files/Cache/HomeCacheTest.php +++ b/tests/lib/Files/Cache/HomeCacheTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,24 +8,20 @@ namespace Test\Files\Cache; -class DummyUser extends \OC\User\User { - /** - * @var string $home - */ - private $home; - - /** - * @var string $uid - */ - private $uid; +use OC\Files\Storage\Home; +use OC\User\User; +use OCP\ITempManager; +use OCP\Server; +class DummyUser extends User { /** * @param string $uid * @param string $home */ - public function __construct($uid, $home) { - $this->home = $home; - $this->uid = $uid; + public function __construct( + private $uid, + private $home, + ) { } /** @@ -61,15 +58,15 @@ class HomeCacheTest extends \Test\TestCase { private $cache; /** - * @var \OC\User\User $user + * @var User $user */ private $user; protected function setUp(): void { parent::setUp(); - $this->user = new DummyUser('foo', \OC::$server->getTempManager()->getTemporaryFolder()); - $this->storage = new \OC\Files\Storage\Home(['user' => $this->user]); + $this->user = new DummyUser('foo', Server::get(ITempManager::class)->getTemporaryFolder()); + $this->storage = new Home(['user' => $this->user]); $this->cache = $this->storage->getCache(); } @@ -78,7 +75,7 @@ class HomeCacheTest extends \Test\TestCase { * that have an unknown size. This makes sure that quota calculation still * works as it's based on the "files" folder size. */ - public function testRootFolderSizeIgnoresUnknownUpdate() { + public function testRootFolderSizeIgnoresUnknownUpdate(): void { $dir1 = 'files/knownsize'; $dir2 = 'files/unknownsize'; $fileData = []; @@ -110,7 +107,7 @@ class HomeCacheTest extends \Test\TestCase { $this->assertFalse($this->cache->inCache($dir2)); } - public function testRootFolderSizeIsFilesSize() { + public function testRootFolderSizeIsFilesSize(): void { $dir1 = 'files'; $afile = 'test.txt'; $fileData = []; diff --git a/tests/lib/Files/Cache/LocalRootScannerTest.php b/tests/lib/Files/Cache/LocalRootScannerTest.php index 204621bbd03..727da2ed698 100644 --- a/tests/lib/Files/Cache/LocalRootScannerTest.php +++ b/tests/lib/Files/Cache/LocalRootScannerTest.php @@ -9,6 +9,8 @@ declare(strict_types=1); namespace Test\Files\Cache; use OC\Files\Storage\LocalRootStorage; +use OCP\ITempManager; +use OCP\Server; use Test\TestCase; /** @@ -21,11 +23,11 @@ class LocalRootScannerTest extends TestCase { protected function setUp(): void { parent::setUp(); - $folder = \OC::$server->getTempManager()->getTemporaryFolder(); + $folder = Server::get(ITempManager::class)->getTemporaryFolder(); $this->storage = new LocalRootStorage(['datadir' => $folder]); } - public function testDontScanUsers() { + public function testDontScanUsers(): void { $this->storage->mkdir('foo'); $this->storage->mkdir('foo/bar'); @@ -33,7 +35,7 @@ class LocalRootScannerTest extends TestCase { $this->assertFalse($this->storage->getCache()->inCache('foo')); } - public function testDoScanAppData() { + public function testDoScanAppData(): void { $this->storage->mkdir('appdata_foo'); $this->storage->mkdir('appdata_foo/bar'); diff --git a/tests/lib/Files/Cache/MoveFromCacheTraitTest.php b/tests/lib/Files/Cache/MoveFromCacheTraitTest.php index f0f143f431f..d580cdca4b9 100644 --- a/tests/lib/Files/Cache/MoveFromCacheTraitTest.php +++ b/tests/lib/Files/Cache/MoveFromCacheTraitTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,9 +8,12 @@ namespace Test\Files\Cache; +use OC\Files\Cache\Cache; use OC\Files\Cache\MoveFromCacheTrait; +use OC\Files\Storage\Temporary; +use OCP\Files\Cache\ICacheEntry; -class FallBackCrossCacheMoveCache extends \OC\Files\Cache\Cache { +class FallBackCrossCacheMoveCache extends Cache { use MoveFromCacheTrait; } @@ -22,9 +26,12 @@ class MoveFromCacheTraitTest extends CacheTest { protected function setUp(): void { parent::setUp(); - $this->storage = new \OC\Files\Storage\Temporary([]); - $this->storage2 = new \OC\Files\Storage\Temporary([]); + $this->storage = new Temporary([]); + $this->storage2 = new Temporary([]); $this->cache = new FallBackCrossCacheMoveCache($this->storage); $this->cache2 = new FallBackCrossCacheMoveCache($this->storage2); + + $this->cache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); + $this->cache2->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); } } diff --git a/tests/lib/Files/Cache/PropagatorTest.php b/tests/lib/Files/Cache/PropagatorTest.php index 8902034db02..2ab213e9567 100644 --- a/tests/lib/Files/Cache/PropagatorTest.php +++ b/tests/lib/Files/Cache/PropagatorTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -16,7 +17,7 @@ use Test\TestCase; * @group DB */ class PropagatorTest extends TestCase { - /** @var IStorage */ + /** @var IStorage */ private $storage; protected function setUp(): void { @@ -38,7 +39,7 @@ class PropagatorTest extends TestCase { return array_combine($paths, $values); } - public function testEtagPropagation() { + public function testEtagPropagation(): void { $paths = ['', 'foo', 'foo/bar']; $oldInfos = $this->getFileInfos($paths); $this->storage->getPropagator()->propagateChange('foo/bar/file.txt', time()); @@ -49,7 +50,7 @@ class PropagatorTest extends TestCase { } } - public function testTimePropagation() { + public function testTimePropagation(): void { $paths = ['', 'foo', 'foo/bar']; $oldTime = time() - 200; $targetTime = time() - 100; @@ -69,7 +70,7 @@ class PropagatorTest extends TestCase { $this->assertEquals($now, $newInfos['']->getMTime()); } - public function testSizePropagation() { + public function testSizePropagation(): void { $paths = ['', 'foo', 'foo/bar']; $oldInfos = $this->getFileInfos($paths); $this->storage->getPropagator()->propagateChange('foo/bar/file.txt', time(), 10); @@ -80,7 +81,7 @@ class PropagatorTest extends TestCase { } } - public function testSizePropagationNoNegative() { + public function testSizePropagationNoNegative(): void { $paths = ['', 'foo', 'foo/bar']; $oldInfos = $this->getFileInfos($paths); $this->storage->getPropagator()->propagateChange('foo/bar/file.txt', time(), -100); @@ -91,7 +92,7 @@ class PropagatorTest extends TestCase { } } - public function testBatchedPropagation() { + public function testBatchedPropagation(): void { $this->storage->mkdir('foo/baz'); $this->storage->mkdir('asd'); $this->storage->file_put_contents('asd/file.txt', 'bar'); @@ -122,7 +123,7 @@ class PropagatorTest extends TestCase { foreach ($oldInfos as $i => $oldInfo) { if ($oldInfo->getPath() !== 'foo/baz') { - $this->assertNotEquals($oldInfo->getEtag(), $newInfos[$i]->getEtag()); + $this->assertNotEquals($oldInfo->getEtag(), $newInfos[$i]->getEtag(), "etag for {$oldInfo->getPath()} not updated"); } } diff --git a/tests/lib/Files/Cache/ScannerTest.php b/tests/lib/Files/Cache/ScannerTest.php index bc911baba0c..123c13893f7 100644 --- a/tests/lib/Files/Cache/ScannerTest.php +++ b/tests/lib/Files/Cache/ScannerTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -14,6 +15,8 @@ use OC\Files\Cache\Scanner; use OC\Files\Storage\Storage; use OC\Files\Storage\Temporary; use OCP\Files\Cache\IScanner; +use OCP\IDBConnection; +use OCP\Server; use Test\TestCase; /** @@ -42,7 +45,7 @@ class ScannerTest extends TestCase { parent::tearDown(); } - public function testFile() { + public function testFile(): void { $data = "dummy file data\n"; $this->storage->file_put_contents('foo.txt', $data); $this->scanner->scanFile('foo.txt'); @@ -63,11 +66,11 @@ class ScannerTest extends TestCase { $this->assertEquals($cachedData['mimetype'], 'image/png'); } - public function testFile4Byte() { + public function testFile4Byte(): void { $data = "dummy file data\n"; $this->storage->file_put_contents('foo🙈.txt', $data); - if (OC::$server->getDatabaseConnection()->supports4ByteText()) { + if (Server::get(IDBConnection::class)->supports4ByteText()) { $this->assertNotNull($this->scanner->scanFile('foo🙈.txt')); $this->assertTrue($this->cache->inCache('foo🙈.txt'), true); @@ -81,7 +84,7 @@ class ScannerTest extends TestCase { } } - public function testFileInvalidChars() { + public function testFileInvalidChars(): void { $data = "dummy file data\n"; $this->storage->file_put_contents("foo\nbar.txt", $data); @@ -98,7 +101,7 @@ class ScannerTest extends TestCase { $this->storage->file_put_contents('folder/bar.txt', $textData); } - public function testFolder() { + public function testFolder(): void { $this->fillTestFolders(); $this->scanner->scan(''); @@ -120,7 +123,7 @@ class ScannerTest extends TestCase { $this->assertEquals($cachedDataFolder2['size'], $cachedDataText2['size']); } - public function testShallow() { + public function testShallow(): void { $this->fillTestFolders(); $this->scanner->scan('', IScanner::SCAN_SHALLOW); @@ -148,7 +151,7 @@ class ScannerTest extends TestCase { $this->assertNotEquals($cachedDataFolder['size'], -1); } - public function testBackgroundScan() { + public function testBackgroundScan(): void { $this->fillTestFolders(); $this->storage->mkdir('folder2'); $this->storage->file_put_contents('folder2/bar.txt', 'foobar'); @@ -170,7 +173,7 @@ class ScannerTest extends TestCase { $this->assertFalse($this->cache->getIncomplete()); } - public function testBackgroundScanOnlyRecurseIncomplete() { + public function testBackgroundScanOnlyRecurseIncomplete(): void { $this->fillTestFolders(); $this->storage->mkdir('folder2'); $this->storage->file_put_contents('folder2/bar.txt', 'foobar'); @@ -196,7 +199,7 @@ class ScannerTest extends TestCase { $this->assertFalse($this->cache->getIncomplete()); } - public function testBackgroundScanNestedIncompleteFolders() { + public function testBackgroundScanNestedIncompleteFolders(): void { $this->storage->mkdir('folder'); $this->scanner->backgroundScan(); @@ -234,7 +237,7 @@ class ScannerTest extends TestCase { $this->assertEquals(6, $this->cache->get('folder/subfolder2')['size']); } - public function testReuseExisting() { + public function testReuseExisting(): void { $this->fillTestFolders(); $this->scanner->scan(''); @@ -273,7 +276,7 @@ class ScannerTest extends TestCase { $this->assertEquals($oldData['size'], $newData['size']); } - public function testRemovedFile() { + public function testRemovedFile(): void { $this->fillTestFolders(); $this->scanner->scan(''); @@ -283,7 +286,7 @@ class ScannerTest extends TestCase { $this->assertFalse($this->cache->inCache('foo.txt')); } - public function testRemovedFolder() { + public function testRemovedFolder(): void { $this->fillTestFolders(); $this->scanner->scan(''); @@ -294,7 +297,7 @@ class ScannerTest extends TestCase { $this->assertFalse($this->cache->inCache('folder/bar.txt')); } - public function testScanRemovedFile() { + public function testScanRemovedFile(): void { $this->fillTestFolders(); $this->scanner->scan(''); @@ -304,7 +307,7 @@ class ScannerTest extends TestCase { $this->assertFalse($this->cache->inCache('folder/bar.txt')); } - public function testETagRecreation() { + public function testETagRecreation(): void { $this->fillTestFolders(); $this->scanner->scan('folder/bar.txt'); @@ -330,14 +333,14 @@ class ScannerTest extends TestCase { $this->assertNotEmpty($newData0['etag']); } - public function testRepairParent() { + public function testRepairParent(): void { $this->fillTestFolders(); $this->scanner->scan(''); $this->assertTrue($this->cache->inCache('folder/bar.txt')); $oldFolderId = $this->cache->getId('folder'); // delete the folder without removing the children - $query = OC::$server->getDatabaseConnection()->getQueryBuilder(); + $query = Server::get(IDBConnection::class)->getQueryBuilder(); $query->delete('filecache') ->where($query->expr()->eq('fileid', $query->createNamedParameter($oldFolderId))); $query->execute(); @@ -356,14 +359,14 @@ class ScannerTest extends TestCase { $this->assertEquals($newFolderId, $cachedData['parent']); } - public function testRepairParentShallow() { + public function testRepairParentShallow(): void { $this->fillTestFolders(); $this->scanner->scan(''); $this->assertTrue($this->cache->inCache('folder/bar.txt')); $oldFolderId = $this->cache->getId('folder'); // delete the folder without removing the children - $query = OC::$server->getDatabaseConnection()->getQueryBuilder(); + $query = Server::get(IDBConnection::class)->getQueryBuilder(); $query->delete('filecache') ->where($query->expr()->eq('fileid', $query->createNamedParameter($oldFolderId))); $query->execute(); @@ -383,18 +386,18 @@ class ScannerTest extends TestCase { } /** - * @dataProvider dataTestIsPartialFile * * @param string $path * @param bool $expected */ - public function testIsPartialFile($path, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestIsPartialFile')] + public function testIsPartialFile($path, $expected): void { $this->assertSame($expected, $this->scanner->isPartialFile($path) ); } - public function dataTestIsPartialFile() { + public static function dataTestIsPartialFile(): array { return [ ['foo.txt.part', true], ['/sub/folder/foo.txt.part', true], @@ -404,7 +407,7 @@ class ScannerTest extends TestCase { ]; } - public function testNoETagUnscannedFolder() { + public function testNoETagUnscannedFolder(): void { $this->fillTestFolders(); $this->scanner->scan(''); @@ -423,7 +426,7 @@ class ScannerTest extends TestCase { $this->assertNotEquals($newFolderEntry->getEtag(), $oldFolderEntry->getEtag()); } - public function testNoETagUnscannedSubFolder() { + public function testNoETagUnscannedSubFolder(): void { $this->fillTestFolders(); $this->storage->mkdir('folder/sub'); diff --git a/tests/lib/Files/Cache/SearchBuilderTest.php b/tests/lib/Files/Cache/SearchBuilderTest.php index 57d890fcbcd..ee097044e3b 100644 --- a/tests/lib/Files/Cache/SearchBuilderTest.php +++ b/tests/lib/Files/Cache/SearchBuilderTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -15,6 +16,9 @@ use OCP\Files\IMimeTypeLoader; use OCP\Files\Search\ISearchBinaryOperator; use OCP\Files\Search\ISearchComparison; use OCP\Files\Search\ISearchOperator; +use OCP\FilesMetadata\IFilesMetadataManager; +use OCP\IDBConnection; +use OCP\Server; use Test\TestCase; /** @@ -24,9 +28,12 @@ class SearchBuilderTest extends TestCase { /** @var IQueryBuilder */ private $builder; - /** @var IMimeTypeLoader|\PHPUnit\Framework\MockObject\MockObject */ + /** @var IMimeTypeLoader&\PHPUnit\Framework\MockObject\MockObject */ private $mimetypeLoader; + /** @var IFilesMetadataManager&\PHPUnit\Framework\MockObject\MockObject */ + private $filesMetadataManager; + /** @var SearchBuilder */ private $searchBuilder; @@ -35,8 +42,9 @@ class SearchBuilderTest extends TestCase { protected function setUp(): void { parent::setUp(); - $this->builder = \OC::$server->getDatabaseConnection()->getQueryBuilder(); + $this->builder = Server::get(IDBConnection::class)->getQueryBuilder(); $this->mimetypeLoader = $this->createMock(IMimeTypeLoader::class); + $this->filesMetadataManager = $this->createMock(IFilesMetadataManager::class); $this->mimetypeLoader->expects($this->any()) ->method('getId') @@ -60,7 +68,7 @@ class SearchBuilderTest extends TestCase { [6, 'image'] ]); - $this->searchBuilder = new SearchBuilder($this->mimetypeLoader); + $this->searchBuilder = new SearchBuilder($this->mimetypeLoader, $this->filesMetadataManager); $this->numericStorageId = 10000; $this->builder->select(['fileid']) @@ -71,7 +79,7 @@ class SearchBuilderTest extends TestCase { protected function tearDown(): void { parent::tearDown(); - $builder = \OC::$server->getDatabaseConnection()->getQueryBuilder(); + $builder = Server::get(IDBConnection::class)->getQueryBuilder(); $builder->delete('filecache') ->where($builder->expr()->eq('storage', $builder->createNamedParameter($this->numericStorageId, IQueryBuilder::PARAM_INT))); @@ -104,7 +112,7 @@ class SearchBuilderTest extends TestCase { $data['mimetype'] = 1; } - $builder = \OC::$server->getDatabaseConnection()->getQueryBuilder(); + $builder = Server::get(IDBConnection::class)->getQueryBuilder(); $values = []; foreach ($data as $key => $value) { @@ -129,7 +137,7 @@ class SearchBuilderTest extends TestCase { return $rows; } - public function comparisonProvider() { + public static function comparisonProvider(): array { return [ [new SearchComparison(ISearchComparison::COMPARE_GREATER_THAN, 'mtime', 125), [1]], [new SearchComparison(ISearchComparison::COMPARE_LESS_THAN, 'mtime', 125), [0]], @@ -170,12 +178,12 @@ class SearchBuilderTest extends TestCase { } /** - * @dataProvider comparisonProvider * * @param ISearchOperator $operator * @param array $fileIds */ - public function testComparison(ISearchOperator $operator, array $fileIds) { + #[\PHPUnit\Framework\Attributes\DataProvider('comparisonProvider')] + public function testComparison(ISearchOperator $operator, array $fileIds): void { $fileId = []; $fileId[] = $this->addCacheEntry([ 'path' => 'foobar', diff --git a/tests/lib/Files/Cache/UpdaterLegacyTest.php b/tests/lib/Files/Cache/UpdaterLegacyTest.php index cb51afe7d6a..c71fac2d2dc 100644 --- a/tests/lib/Files/Cache/UpdaterLegacyTest.php +++ b/tests/lib/Files/Cache/UpdaterLegacyTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,9 +8,15 @@ namespace Test\Files\Cache; +use OC\Files\Cache\Cache; +use OC\Files\Cache\Scanner; use OC\Files\Filesystem as Filesystem; +use OC\Files\Storage\Storage; +use OC\Files\Storage\Temporary; use OC\Files\View; use OCP\Files\Mount\IMountManager; +use OCP\IUserManager; +use OCP\Server; /** * Class UpdaterLegacyTest @@ -20,17 +27,17 @@ use OCP\Files\Mount\IMountManager; */ class UpdaterLegacyTest extends \Test\TestCase { /** - * @var \OC\Files\Storage\Storage $storage + * @var Storage $storage */ private $storage; /** - * @var \OC\Files\Cache\Scanner $scanner + * @var Scanner $scanner */ private $scanner; /** - * @var \OC\Files\Cache\Cache $cache + * @var Cache $cache */ private $cache; @@ -39,7 +46,7 @@ class UpdaterLegacyTest extends \Test\TestCase { protected function setUp(): void { parent::setUp(); - $this->storage = new \OC\Files\Storage\Temporary([]); + $this->storage = new Temporary([]); $textData = "dummy file data\n"; $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo/logo.png'); $this->storage->mkdir('folder'); @@ -56,13 +63,13 @@ class UpdaterLegacyTest extends \Test\TestCase { self::$user = $this->getUniqueID(); } - \OC::$server->getUserManager()->createUser(self::$user, 'password'); + Server::get(IUserManager::class)->createUser(self::$user, 'NotAnEasyPassword123456+'); $this->loginAsUser(self::$user); Filesystem::init(self::$user, '/' . self::$user . '/files'); /** @var IMountManager $manager */ - $manager = \OC::$server->get(IMountManager::class); + $manager = Server::get(IMountManager::class); $manager->removeMount('/' . self::$user); Filesystem::mount($this->storage, [], '/' . self::$user . '/files'); @@ -76,7 +83,7 @@ class UpdaterLegacyTest extends \Test\TestCase { } $result = false; - $user = \OC::$server->getUserManager()->get(self::$user); + $user = Server::get(IUserManager::class)->get(self::$user); if ($user !== null) { $result = $user->delete(); } @@ -86,7 +93,7 @@ class UpdaterLegacyTest extends \Test\TestCase { parent::tearDown(); } - public function testWrite() { + public function testWrite(): void { $textSize = strlen("dummy file data\n"); $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo/logo.png'); $this->cache->put('foo.txt', ['mtime' => 100, 'storage_mtime' => 150]); @@ -121,8 +128,8 @@ class UpdaterLegacyTest extends \Test\TestCase { $this->assertGreaterThanOrEqual($rootCachedData['mtime'], $mtime); } - public function testWriteWithMountPoints() { - $storage2 = new \OC\Files\Storage\Temporary([]); + public function testWriteWithMountPoints(): void { + $storage2 = new Temporary([]); $storage2->getScanner()->scan(''); //initialize etags $cache2 = $storage2->getCache(); Filesystem::mount($storage2, [], '/' . self::$user . '/files/folder/substorage'); @@ -147,7 +154,7 @@ class UpdaterLegacyTest extends \Test\TestCase { $this->assertNotSame($oldEtag, $cachedData['etag']); } - public function testDelete() { + public function testDelete(): void { $textSize = strlen("dummy file data\n"); $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo/logo.png'); $rootCachedData = $this->cache->get(''); @@ -182,8 +189,8 @@ class UpdaterLegacyTest extends \Test\TestCase { $this->assertGreaterThanOrEqual($rootCachedData['mtime'], $cachedData['mtime']); } - public function testDeleteWithMountPoints() { - $storage2 = new \OC\Files\Storage\Temporary([]); + public function testDeleteWithMountPoints(): void { + $storage2 = new Temporary([]); $cache2 = $storage2->getCache(); Filesystem::mount($storage2, [], '/' . self::$user . '/files/folder/substorage'); Filesystem::file_put_contents('folder/substorage/foo.txt', 'asd'); @@ -208,7 +215,7 @@ class UpdaterLegacyTest extends \Test\TestCase { $this->assertGreaterThanOrEqual($folderCachedData['mtime'], $cachedData['mtime']); } - public function testRename() { + public function testRename(): void { $textSize = strlen("dummy file data\n"); $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo/logo.png'); $rootCachedData = $this->cache->get(''); @@ -230,7 +237,7 @@ class UpdaterLegacyTest extends \Test\TestCase { $this->assertNotSame($rootCachedData['etag'], $cachedData['etag']); } - public function testRenameExtension() { + public function testRenameExtension(): void { $fooCachedData = $this->cache->get('foo.txt'); $this->assertEquals('text/plain', $fooCachedData['mimetype']); Filesystem::rename('foo.txt', 'foo.abcd'); @@ -238,8 +245,8 @@ class UpdaterLegacyTest extends \Test\TestCase { $this->assertEquals('application/octet-stream', $fooCachedData['mimetype']); } - public function testRenameWithMountPoints() { - $storage2 = new \OC\Files\Storage\Temporary([]); + public function testRenameWithMountPoints(): void { + $storage2 = new Temporary([]); $cache2 = $storage2->getCache(); Filesystem::mount($storage2, [], '/' . self::$user . '/files/folder/substorage'); Filesystem::file_put_contents('folder/substorage/foo.txt', 'asd'); @@ -271,7 +278,7 @@ class UpdaterLegacyTest extends \Test\TestCase { // $this->assertEquals($mtime, $cachedData['mtime']); } - public function testTouch() { + public function testTouch(): void { $rootCachedData = $this->cache->get(''); $fooCachedData = $this->cache->get('foo.txt'); Filesystem::touch('foo.txt'); diff --git a/tests/lib/Files/Cache/UpdaterTest.php b/tests/lib/Files/Cache/UpdaterTest.php index bfc17e64467..65c47cb9ae6 100644 --- a/tests/lib/Files/Cache/UpdaterTest.php +++ b/tests/lib/Files/Cache/UpdaterTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,8 +8,14 @@ namespace Test\Files\Cache; +use OC\Files\Cache\Cache; use OC\Files\Filesystem; +use OC\Files\ObjectStore\ObjectStoreStorage; +use OC\Files\ObjectStore\StorageObjectStore; +use OC\Files\Storage\Storage; use OC\Files\Storage\Temporary; +use OC\Files\View; +use OCP\Files\Storage\IStorage; /** * Class UpdaterTest @@ -19,17 +26,17 @@ use OC\Files\Storage\Temporary; */ class UpdaterTest extends \Test\TestCase { /** - * @var \OC\Files\Storage\Storage + * @var Storage */ protected $storage; /** - * @var \OC\Files\Cache\Cache + * @var Cache */ protected $cache; /** - * @var \OC\Files\View + * @var View */ protected $view; @@ -53,7 +60,7 @@ class UpdaterTest extends \Test\TestCase { parent::tearDown(); } - public function testNewFile() { + public function testNewFile(): void { $this->storage->file_put_contents('foo.txt', 'bar'); $this->assertFalse($this->cache->inCache('foo.txt')); @@ -65,7 +72,7 @@ class UpdaterTest extends \Test\TestCase { $this->assertEquals('text/plain', $cached['mimetype']); } - public function testUpdatedFile() { + public function testUpdatedFile(): void { $this->storage->file_put_contents('foo.txt', 'bar'); $this->updater->update('foo.txt'); @@ -84,7 +91,7 @@ class UpdaterTest extends \Test\TestCase { $this->assertEquals(6, $cached['size']); } - public function testParentSize() { + public function testParentSize(): void { $this->storage->getScanner()->scan(''); $parentCached = $this->cache->get(''); @@ -121,7 +128,7 @@ class UpdaterTest extends \Test\TestCase { $this->assertEquals(0, $parentCached['size']); } - public function testMove() { + public function testMove(): void { $this->storage->file_put_contents('foo.txt', 'qwerty'); $this->updater->update('foo.txt'); @@ -146,7 +153,7 @@ class UpdaterTest extends \Test\TestCase { $this->assertEquals($cached['fileid'], $cachedTarget['fileid']); } - public function testMoveNonExistingOverwrite() { + public function testMoveNonExistingOverwrite(): void { $this->storage->file_put_contents('bar.txt', 'qwerty'); $this->updater->update('bar.txt'); @@ -164,7 +171,7 @@ class UpdaterTest extends \Test\TestCase { $this->assertEquals($cached['fileid'], $cachedTarget['fileid']); } - public function testUpdateStorageMTime() { + public function testUpdateStorageMTime(): void { $this->storage->mkdir('sub'); $this->storage->mkdir('sub2'); $this->storage->file_put_contents('sub/foo.txt', 'qwerty'); @@ -205,7 +212,7 @@ class UpdaterTest extends \Test\TestCase { $this->assertNotEquals($testmtime, $cachedTargetParent['mtime'], 'target folder mtime changed, not from storage'); } - public function testNewFileDisabled() { + public function testNewFileDisabled(): void { $this->storage->file_put_contents('foo.txt', 'bar'); $this->assertFalse($this->cache->inCache('foo.txt')); @@ -215,7 +222,7 @@ class UpdaterTest extends \Test\TestCase { $this->assertFalse($this->cache->inCache('foo.txt')); } - public function testMoveCrossStorage() { + public function testMoveCrossStorage(): void { $storage2 = new Temporary([]); $cache2 = $storage2->getCache(); Filesystem::mount($storage2, [], '/bar'); @@ -246,7 +253,7 @@ class UpdaterTest extends \Test\TestCase { $this->assertEquals($cached['fileid'], $cachedTarget['fileid']); } - public function testMoveFolderCrossStorage() { + public function testMoveFolderCrossStorage(): void { $storage2 = new Temporary([]); $cache2 = $storage2->getCache(); Filesystem::mount($storage2, [], '/bar'); @@ -301,4 +308,34 @@ class UpdaterTest extends \Test\TestCase { $this->assertEquals($old['mimetype'], $new['mimetype']); } } + + public static function changeExtensionProvider(): array { + return [ + [new Temporary()], + [new ObjectStoreStorage(['objectstore' => new StorageObjectStore(new Temporary())])] + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('changeExtensionProvider')] + public function testChangeExtension(IStorage $storage) { + $updater = $storage->getUpdater(); + $cache = $storage->getCache(); + $storage->file_put_contents('foo', 'qwerty'); + $updater->update('foo'); + + $bareCached = $cache->get('foo'); + $this->assertEquals('application/octet-stream', $bareCached->getMimeType()); + + $storage->rename('foo', 'foo.txt'); + $updater->renameFromStorage($storage, 'foo', 'foo.txt'); + + $cached = $cache->get('foo.txt'); + $this->assertEquals('text/plain', $cached->getMimeType()); + + $storage->rename('foo.txt', 'foo.md'); + $updater->renameFromStorage($storage, 'foo.txt', 'foo.md'); + + $cachedTarget = $cache->get('foo.md'); + $this->assertEquals('text/markdown', $cachedTarget->getMimeType()); + } } diff --git a/tests/lib/Files/Cache/WatcherTest.php b/tests/lib/Files/Cache/WatcherTest.php index d4a44ca6aa0..6d0a8e0886b 100644 --- a/tests/lib/Files/Cache/WatcherTest.php +++ b/tests/lib/Files/Cache/WatcherTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,6 +8,10 @@ namespace Test\Files\Cache; +use OC\Files\Cache\Watcher; +use OC\Files\Storage\Storage; +use OC\Files\Storage\Temporary; + /** * Class WatcherTest * @@ -16,7 +21,7 @@ namespace Test\Files\Cache; */ class WatcherTest extends \Test\TestCase { /** - * @var \OC\Files\Storage\Storage[] $storages + * @var Storage[] $storages */ private $storages = []; @@ -40,11 +45,11 @@ class WatcherTest extends \Test\TestCase { /** * @medium */ - public function testWatcher() { + public function testWatcher(): void { $storage = $this->getTestStorage(); $cache = $storage->getCache(); $updater = $storage->getWatcher(); - $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE); + $updater->setPolicy(Watcher::CHECK_ONCE); //set the mtime to the past so it can detect an mtime change $cache->put('', ['storage_mtime' => 10]); @@ -81,11 +86,11 @@ class WatcherTest extends \Test\TestCase { /** * @medium */ - public function testFileToFolder() { + public function testFileToFolder(): void { $storage = $this->getTestStorage(); $cache = $storage->getCache(); $updater = $storage->getWatcher(); - $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE); + $updater->setPolicy(Watcher::CHECK_ONCE); //set the mtime to the past so it can detect an mtime change $cache->put('', ['storage_mtime' => 10]); @@ -102,7 +107,7 @@ class WatcherTest extends \Test\TestCase { $storage = $this->getTestStorage(); $cache = $storage->getCache(); $updater = $storage->getWatcher(); - $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE); + $updater->setPolicy(Watcher::CHECK_ONCE); //set the mtime to the past so it can detect an mtime change $cache->put('foo.txt', ['storage_mtime' => 10]); @@ -116,7 +121,7 @@ class WatcherTest extends \Test\TestCase { $this->assertTrue($cache->inCache('foo.txt/bar.txt')); } - public function testPolicyNever() { + public function testPolicyNever(): void { $storage = $this->getTestStorage(); $cache = $storage->getCache(); $updater = $storage->getWatcher(); @@ -124,7 +129,7 @@ class WatcherTest extends \Test\TestCase { //set the mtime to the past so it can detect an mtime change $cache->put('foo.txt', ['storage_mtime' => 10]); - $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_NEVER); + $updater->setPolicy(Watcher::CHECK_NEVER); $storage->file_put_contents('foo.txt', 'q'); $this->assertFalse($updater->checkUpdate('foo.txt')); @@ -134,7 +139,7 @@ class WatcherTest extends \Test\TestCase { $this->assertFalse($updater->checkUpdate('foo.txt')); } - public function testPolicyOnce() { + public function testPolicyOnce(): void { $storage = $this->getTestStorage(); $cache = $storage->getCache(); $updater = $storage->getWatcher(); @@ -142,7 +147,7 @@ class WatcherTest extends \Test\TestCase { //set the mtime to the past so it can detect an mtime change $cache->put('foo.txt', ['storage_mtime' => 10]); - $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE); + $updater->setPolicy(Watcher::CHECK_ONCE); $storage->file_put_contents('foo.txt', 'q'); $this->assertTrue($updater->checkUpdate('foo.txt')); @@ -152,7 +157,7 @@ class WatcherTest extends \Test\TestCase { $this->assertFalse($updater->checkUpdate('foo.txt')); } - public function testPolicyAlways() { + public function testPolicyAlways(): void { $storage = $this->getTestStorage(); $cache = $storage->getCache(); $updater = $storage->getWatcher(); @@ -160,7 +165,7 @@ class WatcherTest extends \Test\TestCase { //set the mtime to the past so it can detect an mtime change $cache->put('foo.txt', ['storage_mtime' => 10]); - $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_ALWAYS); + $updater->setPolicy(Watcher::CHECK_ALWAYS); $storage->file_put_contents('foo.txt', 'q'); $this->assertTrue($updater->checkUpdate('foo.txt')); @@ -172,10 +177,10 @@ class WatcherTest extends \Test\TestCase { /** * @param bool $scan - * @return \OC\Files\Storage\Storage + * @return Storage */ private function getTestStorage($scan = true) { - $storage = new \OC\Files\Storage\Temporary([]); + $storage = new Temporary([]); $textData = "dummy file data\n"; $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo/logo.png'); $storage->mkdir('folder'); diff --git a/tests/lib/Files/Cache/Wrapper/CacheJailTest.php b/tests/lib/Files/Cache/Wrapper/CacheJailTest.php index d0a6f99cb19..8ac3492fbd2 100644 --- a/tests/lib/Files/Cache/Wrapper/CacheJailTest.php +++ b/tests/lib/Files/Cache/Wrapper/CacheJailTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,12 +8,15 @@ namespace Test\Files\Cache\Wrapper; +use OC\Files\Cache\Cache; 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; use OC\User\User; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Cache\ICacheEntry; use OCP\Files\Search\ISearchComparison; use Test\Files\Cache\CacheTest; @@ -25,23 +29,25 @@ use Test\Files\Cache\CacheTest; */ class CacheJailTest extends CacheTest { /** - * @var \OC\Files\Cache\Cache $sourceCache + * @var Cache $sourceCache */ protected $sourceCache; protected function setUp(): void { parent::setUp(); - $this->storage->mkdir('foo'); + $this->storage->mkdir('jail'); $this->sourceCache = $this->cache; - $this->cache = new \OC\Files\Cache\Wrapper\CacheJail($this->sourceCache, 'foo'); + $this->cache = new CacheJail($this->sourceCache, 'jail'); + $this->cache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); } - public function testSearchOutsideJail() { + public function testSearchOutsideJail(): void { $this->storage->getScanner()->scan(''); - $file1 = 'foo/foobar'; + $file1 = 'jail/foobar'; $file2 = 'folder/foobar'; $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder']; + $this->sourceCache->insert('folder', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $this->sourceCache->put($file1, $data1); $this->sourceCache->put($file2, $data1); @@ -52,20 +58,20 @@ class CacheJailTest extends CacheTest { $this->assertEquals('foobar', $result[0]['path']); $result = $this->cache->search('%foo%'); - $this->assertCount(2, $result); + $this->assertCount(1, $result); usort($result, function ($a, $b) { return $a['path'] <=> $b['path']; }); - $this->assertEquals('', $result[0]['path']); - $this->assertEquals('foobar', $result[1]['path']); + $this->assertEquals('foobar', $result[0]['path']); } - public function testSearchMimeOutsideJail() { + public function testSearchMimeOutsideJail(): void { $this->storage->getScanner()->scan(''); - $file1 = 'foo/foobar'; + $file1 = 'jail/foobar'; $file2 = 'folder/foobar'; $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder']; + $this->sourceCache->insert('folder', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $this->sourceCache->put($file1, $data1); $this->sourceCache->put($file2, $data1); @@ -76,12 +82,14 @@ class CacheJailTest extends CacheTest { $this->assertEquals('foobar', $result[0]['path']); } - public function testSearchQueryOutsideJail() { + public function testSearchQueryOutsideJail(): void { $this->storage->getScanner()->scan(''); - $file1 = 'foo/foobar'; + $file1 = 'jail/foobar'; $file2 = 'folder/foobar'; $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder']; + + $this->sourceCache->insert('folder', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $this->sourceCache->put($file1, $data1); $this->sourceCache->put($file2, $data1); @@ -92,19 +100,19 @@ class CacheJailTest extends CacheTest { $this->assertCount(1, $result); $this->assertEquals('foobar', $result[0]['path']); - $query = new SearchQuery(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'name', 'foo'), 10, 0, [], $user); + $query = new SearchQuery(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'name', 'jail'), 10, 0, [], $user); $result = $this->cache->searchQuery($query); $this->assertCount(1, $result); $this->assertEquals('', $result[0]['path']); } - public function testClearKeepEntriesOutsideJail() { - $file1 = 'foo/foobar'; - $file2 = 'foo/foobar/asd'; + public function testClearKeepEntriesOutsideJail(): void { + $file1 = 'jail/foobar'; + $file2 = 'jail/foobar/asd'; $file3 = 'folder/foobar'; - $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; + $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; - $this->sourceCache->put('foo', $data1); + $this->sourceCache->put('folder', $data1); $this->sourceCache->put($file1, $data1); $this->sourceCache->put($file2, $data1); $this->sourceCache->put($file3, $data1); @@ -115,27 +123,27 @@ class CacheJailTest extends CacheTest { $this->assertTrue($this->sourceCache->inCache('folder/foobar')); } - public function testGetById() { - $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; - $id = $this->sourceCache->put('foo/bar', $data1); + public function testGetById(): void { + $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; + $id = $this->sourceCache->put('jail/bar', $data1); // path from jailed foo of foo/bar is bar $path = $this->cache->getPathById($id); $this->assertEquals('bar', $path); // path from jailed '' of foo/bar is foo/bar - $this->cache = new \OC\Files\Cache\Wrapper\CacheJail($this->sourceCache, ''); + $this->cache = new CacheJail($this->sourceCache, ''); $path = $this->cache->getPathById($id); - $this->assertEquals('foo/bar', $path); + $this->assertEquals('jail/bar', $path); } - public function testGetIncomplete() { + public function testGetIncomplete(): void { //not supported $this->addToAssertionCount(1); } - public function testMoveFromJail() { - $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; + public function testMoveFromJail(): void { + $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; $this->sourceCache->put('source', $folderData); $this->sourceCache->put('source/foo', $folderData); @@ -150,8 +158,8 @@ class CacheJailTest extends CacheTest { $this->assertTrue($this->sourceCache->inCache('target/foo/bar')); } - public function testMoveToJail() { - $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; + public function testMoveToJail(): void { + $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; $this->sourceCache->put('source', $folderData); $this->sourceCache->put('source/foo', $folderData); @@ -166,8 +174,8 @@ class CacheJailTest extends CacheTest { $this->assertTrue($this->sourceCache->inCache('target/foo/bar')); } - public function testMoveBetweenJail() { - $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory']; + public function testMoveBetweenJail(): void { + $folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]; $this->sourceCache->put('source', $folderData); $this->sourceCache->put('source/foo', $folderData); @@ -183,46 +191,46 @@ class CacheJailTest extends CacheTest { $this->assertTrue($this->sourceCache->inCache('target/foo/bar')); } - public function testSearchNested() { + public function testSearchNested(): void { $this->storage->getScanner()->scan(''); - $file1 = 'foo'; - $file2 = 'foo/bar'; - $file3 = 'foo/bar/asd'; + $file1 = 'jail'; + $file2 = 'jail/bar'; + $file3 = 'jail/bar/asd'; $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder']; $this->sourceCache->put($file1, $data1); $this->sourceCache->put($file2, $data1); $this->sourceCache->put($file3, $data1); - $nested = new \OC\Files\Cache\Wrapper\CacheJail($this->cache, 'bar'); + $nested = new CacheJail($this->cache, 'bar'); $result = $nested->search('%asd%'); $this->assertCount(1, $result); $this->assertEquals('asd', $result[0]['path']); } - public function testRootJail() { + public function testRootJail(): void { $this->storage->getScanner()->scan(''); - $file1 = 'foo'; - $file2 = 'foo/bar'; - $file3 = 'foo/bar/asd'; + $file1 = 'jail'; + $file2 = 'jail/bar'; + $file3 = 'jail/bar/asd'; $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder']; $this->sourceCache->put($file1, $data1); $this->sourceCache->put($file2, $data1); $this->sourceCache->put($file3, $data1); - $nested = new \OC\Files\Cache\Wrapper\CacheJail($this->sourceCache, ''); + $nested = new CacheJail($this->sourceCache, ''); $result = $nested->search('%asd%'); $this->assertCount(1, $result); - $this->assertEquals('foo/bar/asd', $result[0]['path']); + $this->assertEquals('jail/bar/asd', $result[0]['path']); } - public function testWatcher() { + public function testWatcher(): void { $storage = new Jail([ 'storage' => $this->storage, - 'root' => 'foo' + 'root' => 'jail' ]); $storage->getScanner()->scan(''); $storage->file_put_contents('bar', 'asd'); @@ -232,10 +240,10 @@ class CacheJailTest extends CacheTest { $this->assertTrue($this->cache->inCache('bar')); } - public function testWatcherAfterInnerWatcher() { + public function testWatcherAfterInnerWatcher(): void { $storage = new Jail([ 'storage' => $this->storage, - 'root' => 'foo' + 'root' => 'jail' ]); $storage->getScanner()->scan(''); $storage->file_put_contents('bar', 'asd'); @@ -247,4 +255,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/Cache/Wrapper/CachePermissionsMaskTest.php b/tests/lib/Files/Cache/Wrapper/CachePermissionsMaskTest.php index d3eb8be7af9..4fbeafc9270 100644 --- a/tests/lib/Files/Cache/Wrapper/CachePermissionsMaskTest.php +++ b/tests/lib/Files/Cache/Wrapper/CachePermissionsMaskTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,6 +8,8 @@ namespace Test\Files\Cache\Wrapper; +use OC\Files\Cache\Cache; +use OC\Files\Cache\Wrapper\CachePermissionsMask; use OCP\Constants; use Test\Files\Cache\CacheTest; @@ -19,7 +22,7 @@ use Test\Files\Cache\CacheTest; */ class CachePermissionsMaskTest extends CacheTest { /** - * @var \OC\Files\Cache\Cache $sourceCache + * @var Cache $sourceCache */ protected $sourceCache; @@ -31,10 +34,10 @@ class CachePermissionsMaskTest extends CacheTest { } protected function getMaskedCached($mask) { - return new \OC\Files\Cache\Wrapper\CachePermissionsMask($this->sourceCache, $mask); + return new CachePermissionsMask($this->sourceCache, $mask); } - public function maskProvider() { + public static function maskProvider(): array { return [ [Constants::PERMISSION_ALL], [Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE], @@ -44,10 +47,10 @@ class CachePermissionsMaskTest extends CacheTest { } /** - * @dataProvider maskProvider * @param int $mask */ - public function testGetMasked($mask) { + #[\PHPUnit\Framework\Attributes\DataProvider('maskProvider')] + public function testGetMasked($mask): void { $cache = $this->getMaskedCached($mask); $data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain', 'permissions' => Constants::PERMISSION_ALL]; $this->sourceCache->put('foo', $data); @@ -61,10 +64,10 @@ class CachePermissionsMaskTest extends CacheTest { } /** - * @dataProvider maskProvider * @param int $mask */ - public function testGetFolderContentMasked($mask) { + #[\PHPUnit\Framework\Attributes\DataProvider('maskProvider')] + public function testGetFolderContentMasked($mask): void { $this->storage->mkdir('foo'); $this->storage->file_put_contents('foo/bar', 'asd'); $this->storage->file_put_contents('foo/asd', 'bar'); @@ -80,10 +83,10 @@ class CachePermissionsMaskTest extends CacheTest { } /** - * @dataProvider maskProvider * @param int $mask */ - public function testSearchMasked($mask) { + #[\PHPUnit\Framework\Attributes\DataProvider('maskProvider')] + public function testSearchMasked($mask): void { $this->storage->mkdir('foo'); $this->storage->file_put_contents('foo/bar', 'asd'); $this->storage->file_put_contents('foo/foobar', 'bar'); diff --git a/tests/lib/Files/Config/UserMountCacheTest.php b/tests/lib/Files/Config/UserMountCacheTest.php index 13690096d3a..6a3dc6a6d7e 100644 --- a/tests/lib/Files/Config/UserMountCacheTest.php +++ b/tests/lib/Files/Config/UserMountCacheTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,18 +8,26 @@ namespace Test\Files\Config; +use OC\DB\Exceptions\DbalException; use OC\DB\QueryBuilder\Literal; +use OC\Files\Cache\Cache; +use OC\Files\Config\UserMountCache; use OC\Files\Mount\MountPoint; use OC\Files\Storage\Storage; use OC\User\Manager; 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; use OCP\IDBConnection; use OCP\IUserManager; +use OCP\Server; use Psr\Log\LoggerInterface; use Test\TestCase; use Test\Util\User\Dummy; @@ -27,28 +36,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(); + + $this->connection = Server::get(IDBConnection::class); + $config = $this->getMockBuilder(IConfig::class) ->disableOriginalConstructor() ->getMock(); @@ -60,13 +60,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->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 { @@ -86,23 +95,19 @@ class UserMountCacheTest extends TestCase { private function getStorage($storageId, $rootInternalPath = '') { $rootId = $this->createCacheEntry($rootInternalPath, $storageId); - $storageCache = $this->getMockBuilder('\OC\Files\Cache\Storage') - ->disableOriginalConstructor() - ->getMock(); + $storageCache = $this->createMock(\OC\Files\Cache\Storage::class); $storageCache->expects($this->any()) ->method('getNumericId') ->willReturn($storageId); - $cache = $this->getMockBuilder('\OC\Files\Cache\Cache') - ->disableOriginalConstructor() - ->getMock(); + $cache = $this->createMock(Cache::class); $cache->expects($this->any()) ->method('getId') ->willReturn($rootId); + $cache->method('getNumericStorageId') + ->willReturn($storageId); - $storage = $this->getMockBuilder('\OC\Files\Storage\Storage') - ->disableOriginalConstructor() - ->getMock(); + $storage = $this->createMock(Storage::class); $storage->expects($this->any()) ->method('getStorageCache') ->willReturn($storageCache); @@ -118,10 +123,15 @@ class UserMountCacheTest extends TestCase { } private function keyForMount(MountPoint $mount): string { - return $mount->getStorageRootId().'::'.$mount->getMountPoint(); + return $mount->getStorageRootId() . '::' . $mount->getMountPoint(); } - public function testNewMounts() { + 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); @@ -141,7 +151,12 @@ class UserMountCacheTest extends TestCase { $this->assertEquals($storage->getStorageCache()->getNumericId(), $cachedMount->getStorageId()); } - public function testSameMounts() { + 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); @@ -165,7 +180,19 @@ class UserMountCacheTest extends TestCase { $this->assertEquals($storage->getStorageCache()->getNumericId(), $cachedMount->getStorageId()); } - public function testRemoveMounts() { + 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); @@ -184,7 +211,20 @@ class UserMountCacheTest extends TestCase { $this->assertCount(0, $cachedMounts); } - public function testChangeMounts() { + 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); @@ -207,7 +247,19 @@ class UserMountCacheTest extends TestCase { $this->assertEquals('/foo/', $cachedMount->getMountPoint()); } - public function testChangeMountId() { + 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); @@ -230,7 +282,7 @@ class UserMountCacheTest extends TestCase { $this->assertEquals(1, $cachedMount->getMountId()); } - public function testGetMountsForUser() { + public function testGetMountsForUser(): void { $user1 = $this->userManager->get('u1'); $user2 = $this->userManager->get('u2'); $user3 = $this->userManager->get('u3'); @@ -267,7 +319,7 @@ class UserMountCacheTest extends TestCase { $this->assertEmpty($cachedMounts); } - public function testGetMountsByStorageId() { + public function testGetMountsByStorageId(): void { $user1 = $this->userManager->get('u1'); $user2 = $this->userManager->get('u2'); @@ -297,7 +349,7 @@ class UserMountCacheTest extends TestCase { $this->assertEquals(2, $cachedMounts[1]->getStorageId()); } - public function testGetMountsByRootId() { + public function testGetMountsByRootId(): void { $user1 = $this->userManager->get('u1'); $user2 = $this->userManager->get('u2'); @@ -335,34 +387,43 @@ class UserMountCacheTest extends TestCase { private function createCacheEntry($internalPath, $storageId, $size = 0) { $internalPath = trim($internalPath, '/'); - $inserted = $this->connection->insertIfNotExist('*PREFIX*filecache', [ - 'storage' => $storageId, - 'path' => $internalPath, - 'path_hash' => md5($internalPath), - 'parent' => -1, - 'name' => basename($internalPath), - 'mimetype' => 0, - 'mimepart' => 0, - 'size' => $size, - 'storage_mtime' => 0, - 'encrypted' => 0, - 'unencrypted_size' => 0, - 'etag' => '', - 'permissions' => 31 - ], ['storage', 'path_hash']); - if ($inserted) { - $id = (int)$this->connection->lastInsertId('*PREFIX*filecache'); + try { + $query = $this->connection->getQueryBuilder(); + $query->insert('filecache') + ->values([ + 'storage' => $query->createNamedParameter($storageId), + 'path' => $query->createNamedParameter($internalPath), + 'path_hash' => $query->createNamedParameter(md5($internalPath)), + 'parent' => $query->createNamedParameter(-1, IQueryBuilder::PARAM_INT), + 'name' => $query->createNamedParameter(basename($internalPath)), + 'mimetype' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT), + 'mimepart' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT), + 'size' => $query->createNamedParameter($size), + 'storage_mtime' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT), + 'encrypted' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT), + 'unencrypted_size' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT), + 'etag' => $query->createNamedParameter(''), + 'permissions' => $query->createNamedParameter(31, IQueryBuilder::PARAM_INT), + ]); + $query->executeStatement(); + $id = $query->getLastInsertId(); $this->fileIds[] = $id; - } else { - $sql = 'SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` =?'; - $query = $this->connection->prepare($sql); - $query->execute([$storageId, md5($internalPath)]); - return (int)$query->fetchOne(); + } catch (DbalException $e) { + if ($e->getReason() === DbalException::REASON_UNIQUE_CONSTRAINT_VIOLATION) { + $query = $this->connection->getQueryBuilder(); + $query->select('fileid') + ->from('filecache') + ->where($query->expr()->eq('storage', $query->createNamedParameter($storageId))) + ->andWhere($query->expr()->eq('path_hash', $query->createNamedParameter(md5($internalPath)))); + $id = (int)$query->execute()->fetchColumn(); + } else { + throw $e; + } } return $id; } - public function testGetMountsForFileIdRootId() { + public function testGetMountsForFileIdRootId(): void { $user1 = $this->userManager->get('u1'); [$storage1, $rootId] = $this->getStorage(2); @@ -382,7 +443,7 @@ class UserMountCacheTest extends TestCase { $this->assertEquals(2, $cachedMounts[0]->getStorageId()); } - public function testGetMountsForFileIdSubFolder() { + public function testGetMountsForFileIdSubFolder(): void { $user1 = $this->userManager->get('u1'); $fileId = $this->createCacheEntry('/foo/bar', 2); @@ -406,7 +467,7 @@ class UserMountCacheTest extends TestCase { $this->assertEquals('/foo/foo/bar', $cachedMounts[0]->getPath()); } - public function testGetMountsForFileIdSubFolderMount() { + public function testGetMountsForFileIdSubFolderMount(): void { $user1 = $this->userManager->get('u1'); [$storage1, $rootId] = $this->getStorage(2); @@ -414,9 +475,9 @@ class UserMountCacheTest extends TestCase { $fileId = $this->createCacheEntry('/foo/bar', 2); - $mount1 = $this->getMockBuilder('\OC\Files\Mount\MountPoint') + $mount1 = $this->getMockBuilder(MountPoint::class) ->setConstructorArgs([$storage1, '/']) - ->setMethods(['getStorageRootId']) + ->onlyMethods(['getStorageRootId']) ->getMock(); $mount1->expects($this->any()) @@ -440,16 +501,16 @@ class UserMountCacheTest extends TestCase { $this->assertEquals('/bar', $cachedMounts[0]->getPath()); } - public function testGetMountsForFileIdSubFolderMountOutside() { + public function testGetMountsForFileIdSubFolderMountOutside(): void { $user1 = $this->userManager->get('u1'); [$storage1, $rootId] = $this->getStorage(2); $folderId = $this->createCacheEntry('/foo', 2); $fileId = $this->createCacheEntry('/bar/asd', 2); - $mount1 = $this->getMockBuilder('\OC\Files\Mount\MountPoint') + $mount1 = $this->getMockBuilder(MountPoint::class) ->setConstructorArgs([$storage1, '/foo/']) - ->setMethods(['getStorageRootId']) + ->onlyMethods(['getStorageRootId']) ->getMock(); $mount1->expects($this->any()) @@ -468,7 +529,7 @@ class UserMountCacheTest extends TestCase { } - public function testGetMountsForFileIdDeletedUser() { + public function testGetMountsForFileIdDeletedUser(): void { $user1 = $this->userManager->get('u1'); [$storage1, $rootId] = $this->getStorage(2); @@ -483,7 +544,7 @@ class UserMountCacheTest extends TestCase { $this->assertEmpty($cachedMounts); } - public function testGetUsedSpaceForUsers() { + public function testGetUsedSpaceForUsers(): void { $user1 = $this->userManager->get('u1'); $user2 = $this->userManager->get('u2'); @@ -496,7 +557,7 @@ class UserMountCacheTest extends TestCase { $mount1 = $this->getMockBuilder(MountPoint::class) ->setConstructorArgs([$storage1, '/u1/']) - ->setMethods(['getStorageRootId', 'getNumericStorageId']) + ->onlyMethods(['getStorageRootId', 'getNumericStorageId']) ->getMock(); $mount1->expects($this->any()) @@ -514,7 +575,7 @@ class UserMountCacheTest extends TestCase { } - public function testMigrateMountProvider() { + public function testMigrateMountProvider(): void { $user1 = $this->userManager->get('u1'); [$storage1, $rootId] = $this->getStorage(2); diff --git a/tests/lib/Files/EtagTest.php b/tests/lib/Files/EtagTest.php index a109a17d250..d1b344ee997 100644 --- a/tests/lib/Files/EtagTest.php +++ b/tests/lib/Files/EtagTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -8,8 +9,15 @@ namespace Test\Files; use OC\Files\Filesystem; +use OC\Files\Utils\Scanner; +use OC\Share\Share; use OCA\Files_Sharing\AppInfo\Application; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\ITempManager; +use OCP\IUserManager; +use OCP\Server; use Psr\Log\LoggerInterface; /** @@ -36,26 +44,26 @@ class EtagTest extends \Test\TestCase { // init files sharing new Application(); - \OC\Share\Share::registerBackend('file', 'OCA\Files_Sharing\ShareBackend\File'); - \OC\Share\Share::registerBackend('folder', 'OCA\Files_Sharing\ShareBackend\Folder', 'file'); + Share::registerBackend('file', 'OCA\Files_Sharing\ShareBackend\File'); + Share::registerBackend('folder', 'OCA\Files_Sharing\ShareBackend\Folder', 'file'); - $config = \OC::$server->getConfig(); + $config = Server::get(IConfig::class); $this->datadir = $config->getSystemValueString('datadirectory'); - $this->tmpDir = \OC::$server->getTempManager()->getTemporaryFolder(); + $this->tmpDir = Server::get(ITempManager::class)->getTemporaryFolder(); $config->setSystemValue('datadirectory', $this->tmpDir); $this->userBackend = new \Test\Util\User\Dummy(); - \OC_User::useBackend($this->userBackend); + Server::get(IUserManager::class)->registerBackend($this->userBackend); } protected function tearDown(): void { - \OC::$server->getConfig()->setSystemValue('datadirectory', $this->datadir); + Server::get(IConfig::class)->setSystemValue('datadirectory', $this->datadir); $this->logout(); parent::tearDown(); } - public function testNewUser() { + public function testNewUser(): void { $user1 = $this->getUniqueID('user_'); $this->userBackend->createUser($user1, ''); @@ -69,7 +77,7 @@ class EtagTest extends \Test\TestCase { $files = ['/foo.txt', '/folder/bar.txt', '/folder/subfolder', '/folder/subfolder/qwerty.txt']; $originalEtags = $this->getEtags($files); - $scanner = new \OC\Files\Utils\Scanner($user1, \OC::$server->getDatabaseConnection(), \OC::$server->query(IEventDispatcher::class), \OC::$server->get(LoggerInterface::class)); + $scanner = new Scanner($user1, Server::get(IDBConnection::class), Server::get(IEventDispatcher::class), Server::get(LoggerInterface::class)); $scanner->backgroundScan('/'); $newEtags = $this->getEtags($files); diff --git a/tests/lib/Files/FileInfoTest.php b/tests/lib/Files/FileInfoTest.php index bc4a25ef622..b3d3c9f0fec 100644 --- a/tests/lib/Files/FileInfoTest.php +++ b/tests/lib/Files/FileInfoTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -27,7 +28,7 @@ class FileInfoTest extends TestCase { $this->config = $this->getMockBuilder(IConfig::class)->getMock(); } - public function testIsMountedHomeStorage() { + public function testIsMountedHomeStorage(): void { $user = $this->createMock(IUser::class); $user->method('getUID') ->willReturn('foo'); @@ -45,7 +46,7 @@ class FileInfoTest extends TestCase { $this->assertFalse($fileInfo->isMounted()); } - public function testIsMountedNonHomeStorage() { + public function testIsMountedNonHomeStorage(): void { $storage = new Temporary(); $fileInfo = new FileInfo( '', diff --git a/tests/lib/Files/FilenameValidatorTest.php b/tests/lib/Files/FilenameValidatorTest.php new file mode 100644 index 00000000000..162275a2cf8 --- /dev/null +++ b/tests/lib/Files/FilenameValidatorTest.php @@ -0,0 +1,491 @@ +<?php + +declare(strict_types=1); + +/*! + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace Test\Files; + +use OC\Files\FilenameValidator; +use OCP\Files\EmptyFileNameException; +use OCP\Files\FileNameTooLongException; +use OCP\Files\InvalidCharacterInPathException; +use OCP\Files\InvalidDirectoryException; +use OCP\Files\InvalidPathException; +use OCP\Files\ReservedWordException; +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\IL10N; +use OCP\L10N\IFactory; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use Test\TestCase; + +class FilenameValidatorTest extends TestCase { + + protected IFactory&MockObject $l10n; + protected IConfig&MockObject $config; + protected IDBConnection&MockObject $database; + protected LoggerInterface&MockObject $logger; + + protected function setUp(): void { + parent::setUp(); + $l10n = $this->createMock(IL10N::class); + $l10n->method('t') + ->willReturnCallback(fn ($string, $params) => sprintf($string, ...$params)); + $this->l10n = $this->createMock(IFactory::class); + $this->l10n + ->method('get') + ->with('core') + ->willReturn($l10n); + + $this->config = $this->createMock(IConfig::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->database = $this->createMock(IDBConnection::class); + $this->database->method('supports4ByteText')->willReturn(true); + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataValidateFilename')] + public function testValidateFilename( + string $filename, + array $forbiddenNames, + array $forbiddenBasenames, + array $forbiddenExtensions, + array $forbiddenCharacters, + ?string $exception, + ): void { + /** @var FilenameValidator&MockObject */ + $validator = $this->getMockBuilder(FilenameValidator::class) + ->onlyMethods([ + 'getForbiddenBasenames', + 'getForbiddenCharacters', + 'getForbiddenExtensions', + 'getForbiddenFilenames', + ]) + ->setConstructorArgs([$this->l10n, $this->database, $this->config, $this->logger]) + ->getMock(); + + $validator->method('getForbiddenBasenames') + ->willReturn($forbiddenBasenames); + $validator->method('getForbiddenCharacters') + ->willReturn($forbiddenCharacters); + $validator->method('getForbiddenExtensions') + ->willReturn($forbiddenExtensions); + $validator->method('getForbiddenFilenames') + ->willReturn($forbiddenNames); + + if ($exception !== null) { + $this->expectException($exception); + } else { + $this->expectNotToPerformAssertions(); + } + $validator->validateFilename($filename); + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataValidateFilename')] + public function testIsFilenameValid( + string $filename, + array $forbiddenNames, + array $forbiddenBasenames, + array $forbiddenExtensions, + array $forbiddenCharacters, + ?string $exception, + ): void { + /** @var FilenameValidator&MockObject */ + $validator = $this->getMockBuilder(FilenameValidator::class) + ->onlyMethods([ + 'getForbiddenBasenames', + 'getForbiddenExtensions', + 'getForbiddenFilenames', + 'getForbiddenCharacters', + ]) + ->setConstructorArgs([$this->l10n, $this->database, $this->config, $this->logger]) + ->getMock(); + + $validator->method('getForbiddenBasenames') + ->willReturn($forbiddenBasenames); + $validator->method('getForbiddenCharacters') + ->willReturn($forbiddenCharacters); + $validator->method('getForbiddenExtensions') + ->willReturn($forbiddenExtensions); + $validator->method('getForbiddenFilenames') + ->willReturn($forbiddenNames); + + + $this->assertEquals($exception === null, $validator->isFilenameValid($filename)); + } + + public static function dataValidateFilename(): array { + return [ + 'valid name' => [ + 'a: b.txt', ['.htaccess'], [], [], [], null + ], + 'forbidden name in the middle is ok' => [ + 'a.htaccess.txt', ['.htaccess'], [], [], [], null + ], + 'valid name with some more parameters' => [ + 'a: b.txt', ['.htaccess'], [], ['exe'], ['~'], null + ], + 'valid name checks only the full name' => [ + '.htaccess.sample', ['.htaccess'], [], [], [], null + ], + 'forbidden name' => [ + '.htaccess', ['.htaccess'], [], [], [], ReservedWordException::class + ], + 'forbidden name - name is case insensitive' => [ + 'COM1', ['.htaccess', 'com1'], [], [], [], ReservedWordException::class + ], + 'forbidden basename' => [ + // needed for Windows namespaces + 'com1.suffix', ['.htaccess'], ['com1'], [], [], ReservedWordException::class + ], + 'forbidden basename case insensitive' => [ + // needed for Windows namespaces + 'COM1.suffix', ['.htaccess'], ['com1'], [], [], ReservedWordException::class + ], + 'forbidden basename for hidden files' => [ + // needed for Windows namespaces + '.thumbs.db', ['.htaccess'], ['.thumbs'], [], [], ReservedWordException::class + ], + 'invalid character' => [ + 'a: b.txt', ['.htaccess'], [], [], [':'], InvalidCharacterInPathException::class + ], + 'invalid path' => [ + '../../foo.bar', ['.htaccess'], [], [], ['/', '\\'], InvalidCharacterInPathException::class, + ], + 'invalid extension' => [ + 'a: b.txt', ['.htaccess'], [], ['.txt'], [], InvalidPathException::class + ], + 'invalid extension case insensitive' => [ + 'a: b.TXT', ['.htaccess'], [], ['.txt'], [], InvalidPathException::class + ], + 'empty filename' => [ + '', [], [], [], [], EmptyFileNameException::class + ], + 'reserved unix name "."' => [ + '.', [], [], [], [], InvalidDirectoryException::class + ], + 'reserved unix name ".."' => [ + '..', [], [], [], [], InvalidDirectoryException::class + ], + 'weird but valid tripple dot name' => [ + '...', [], [], [], [], null // is valid + ], + 'too long filename "."' => [ + str_repeat('a', 251), [], [], [], [], FileNameTooLongException::class + ], + // make sure to not split the list entries as they migh contain Unicode sequences + // in this example the "face in clouds" emoji contains the clouds emoji so only having clouds is ok + ['🌫️.txt', ['.htaccess'], [], [], ['😶🌫️'], null], + // This is the reverse: clouds are forbidden -> so is also the face in the clouds emoji + ['😶🌫️.txt', ['.htaccess'], [], [], ['🌫️'], InvalidCharacterInPathException::class], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('data4ByteUnicode')] + public function testDatabaseDoesNotSupport4ByteText($filename): void { + $database = $this->createMock(IDBConnection::class); + $database->expects($this->once()) + ->method('supports4ByteText') + ->willReturn(false); + $this->expectException(InvalidCharacterInPathException::class); + $validator = new FilenameValidator($this->l10n, $database, $this->config, $this->logger); + $validator->validateFilename($filename); + } + + public static function data4ByteUnicode(): array { + return [ + ['plane 1 𐪅'], + ['emoji 😶🌫️'], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataInvalidAsciiCharacters')] + public function testInvalidAsciiCharactersAreAlwaysForbidden(string $filename): void { + $this->expectException(InvalidPathException::class); + $validator = new FilenameValidator($this->l10n, $this->database, $this->config, $this->logger); + $validator->validateFilename($filename); + } + + public static function dataInvalidAsciiCharacters(): array { + return [ + [\chr(0)], + [\chr(1)], + [\chr(2)], + [\chr(3)], + [\chr(4)], + [\chr(5)], + [\chr(6)], + [\chr(7)], + [\chr(8)], + [\chr(9)], + [\chr(10)], + [\chr(11)], + [\chr(12)], + [\chr(13)], + [\chr(14)], + [\chr(15)], + [\chr(16)], + [\chr(17)], + [\chr(18)], + [\chr(19)], + [\chr(20)], + [\chr(21)], + [\chr(22)], + [\chr(23)], + [\chr(24)], + [\chr(25)], + [\chr(26)], + [\chr(27)], + [\chr(28)], + [\chr(29)], + [\chr(30)], + [\chr(31)], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataIsForbidden')] + public function testIsForbidden(string $filename, array $forbiddenNames, bool $expected): void { + /** @var FilenameValidator&MockObject */ + $validator = $this->getMockBuilder(FilenameValidator::class) + ->onlyMethods(['getForbiddenFilenames']) + ->setConstructorArgs([$this->l10n, $this->database, $this->config, $this->logger]) + ->getMock(); + + $validator->method('getForbiddenFilenames') + ->willReturn($forbiddenNames); + + $this->assertEquals($expected, $validator->isForbidden($filename)); + } + + public static function dataIsForbidden(): array { + return [ + 'valid name' => [ + 'a: b.txt', ['.htaccess'], false + ], + 'valid name with some more parameters' => [ + 'a: b.txt', ['.htaccess'], false + ], + 'valid name as only full forbidden should be matched' => [ + '.htaccess.sample', ['.htaccess'], false, + ], + 'forbidden name' => [ + '.htaccess', ['.htaccess'], true + ], + 'forbidden name - name is case insensitive' => [ + 'COM1', ['.htaccess', 'com1'], true, + ], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetForbiddenExtensions')] + public function testGetForbiddenExtensions(array $configValue, array $expectedValue): void { + $validator = new FilenameValidator($this->l10n, $this->database, $this->config, $this->logger); + $this->config + // only once - then cached + ->expects(self::once()) + ->method('getSystemValue') + ->with('forbidden_filename_extensions', ['.filepart']) + ->willReturn($configValue); + + self::assertEqualsCanonicalizing($expectedValue, $validator->getForbiddenExtensions()); + } + + public static function dataGetForbiddenExtensions(): array { + return [ + // default + [['.filepart'], ['.filepart', '.part']], + // always include .part + [[], ['.part']], + // handle case insensitivity + [['.TXT'], ['.txt', '.part']], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetForbiddenFilenames')] + public function testGetForbiddenFilenames(array $configValue, array $legacyValue, array $expectedValue): void { + $validator = new FilenameValidator($this->l10n, $this->database, $this->config, $this->logger); + $this->config + // only once - then cached + ->expects(self::exactly(2)) + ->method('getSystemValue') + ->willReturnMap([ + ['forbidden_filenames', ['.htaccess'], $configValue], + ['blacklisted_files', [], $legacyValue], + ]); + + $this->logger + ->expects(empty($legacyValue) ? self::never() : self::once()) + ->method('warning'); + + self::assertEqualsCanonicalizing($expectedValue, $validator->getForbiddenFilenames()); + } + + public static function dataGetForbiddenFilenames(): array { + return [ + // default + [['.htaccess'], [], ['.htaccess']], + // with legacy values + [['.htaccess'], ['legacy'], ['.htaccess', 'legacy']], + // handle case insensitivity + [['FileName', '.htaccess'], ['LegAcy'], ['.htaccess', 'filename', 'legacy']], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetForbiddenBasenames')] + public function testGetForbiddenBasenames(array $configValue, array $expectedValue): void { + $validator = new FilenameValidator($this->l10n, $this->database, $this->config, $this->logger); + $this->config + // only once - then cached + ->expects(self::once()) + ->method('getSystemValue') + ->with('forbidden_filename_basenames', []) + ->willReturn($configValue); + + self::assertEqualsCanonicalizing($expectedValue, $validator->getForbiddenBasenames()); + } + + public static function dataGetForbiddenBasenames(): array { + return [ + // default + [[], []], + // with values + [['aux', 'com0'], ['aux', 'com0']], + // handle case insensitivity + [['AuX', 'COM1'], ['aux', 'com1']], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataSanitizeFilename')] + public function testSanitizeFilename( + string $filename, + array $forbiddenNames, + array $forbiddenBasenames, + array $forbiddenExtensions, + array $forbiddenCharacters, + string $expected, + ): void { + /** @var FilenameValidator&MockObject */ + $validator = $this->getMockBuilder(FilenameValidator::class) + ->onlyMethods([ + 'getForbiddenBasenames', + 'getForbiddenExtensions', + 'getForbiddenFilenames', + 'getForbiddenCharacters', + ]) + ->setConstructorArgs([$this->l10n, $this->database, $this->config, $this->logger]) + ->getMock(); + + $validator->method('getForbiddenBasenames') + ->willReturn($forbiddenBasenames); + $validator->method('getForbiddenCharacters') + ->willReturn($forbiddenCharacters); + $validator->method('getForbiddenExtensions') + ->willReturn($forbiddenExtensions); + $validator->method('getForbiddenFilenames') + ->willReturn($forbiddenNames); + + $this->assertEquals($expected, $validator->sanitizeFilename($filename)); + } + + public static function dataSanitizeFilename(): array { + return [ + 'valid name' => [ + 'a * b.txt', ['.htaccess'], [], [], [], 'a * b.txt' + ], + 'forbidden name in the middle is ok' => [ + 'a.htaccess.txt', ['.htaccess'], [], [], [], 'a.htaccess.txt' + ], + 'forbidden name on the beginning' => [ + '.htaccess.sample', ['.htaccess'], [], [], [], '.htaccess.sample' + ], + 'forbidden name' => [ + '.htaccess', ['.htaccess'], [], [], [], '.htaccess (renamed)' + ], + 'forbidden name - name is case insensitive' => [ + 'COM1', ['.htaccess', 'com1'], [], [], [], 'COM1 (renamed)' + ], + 'forbidden basename' => [ + 'com1.suffix', ['.htaccess'], ['com1'], [], [], 'com1 (renamed).suffix' + ], + 'forbidden basename case insensitive' => [ + // needed for Windows namespaces + 'COM1.suffix', ['.htaccess'], ['com1'], [], [], 'COM1 (renamed).suffix' + ], + 'forbidden basename for hidden files' => [ + // needed for Windows namespaces + '.thumbs.db', ['.htaccess'], ['.thumbs'], [], [], '.thumbs (renamed).db' + ], + 'invalid character' => [ + 'a: b.txt', ['.htaccess'], [], [], [':'], 'a_ b.txt', + ], + 'invalid extension' => [ + 'a: b.txt', ['.htaccess'], [], ['.txt'], [], 'a: b' + ], + 'invalid extension case insensitive' => [ + 'a: b.TXT', ['.htaccess'], [], ['.txt'], [], 'a: b' + ], + 'empty filename' => [ + '', [], [], [], [], 'renamed file' + ], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataSanitizeFilenameCharacterReplacement')] + public function testSanitizeFilenameCharacterReplacement( + string $filename, + array $forbiddenCharacters, + ?string $characterReplacement, + ?string $expected, + ): void { + /** @var FilenameValidator&MockObject */ + $validator = $this->getMockBuilder(FilenameValidator::class) + ->onlyMethods([ + 'getForbiddenBasenames', + 'getForbiddenExtensions', + 'getForbiddenFilenames', + 'getForbiddenCharacters', + ]) + ->setConstructorArgs([$this->l10n, $this->database, $this->config, $this->logger]) + ->getMock(); + + $validator->method('getForbiddenBasenames') + ->willReturn([]); + $validator->method('getForbiddenCharacters') + ->willReturn($forbiddenCharacters); + $validator->method('getForbiddenExtensions') + ->willReturn([]); + $validator->method('getForbiddenFilenames') + ->willReturn([]); + + if ($expected === null) { + $this->expectException(\InvalidArgumentException::class); + $validator->sanitizeFilename($filename, $characterReplacement); + } else { + $this->assertEquals($expected, $validator->sanitizeFilename($filename, $characterReplacement)); + } + } + + public static function dataSanitizeFilenameCharacterReplacement(): array { + return [ + 'default' => [ + 'foo*bar', ['*'], null, 'foo_bar' + ], + 'default - underscore not allowed' => [ + 'foo*bar', ['*', '_'], null, 'foo-bar' + ], + 'default - dash and underscore not allowed' => [ + 'foo*bar', ['*', '-', '_'], null, 'foo bar' + ], + 'default - no replacement' => [ + 'foo*bar', ['*', ' ', '_', '-'], null, null + ], + 'custom replacement' => [ + 'foo*bar', ['*'], 'x', 'fooxbar' + ], + ]; + } +} diff --git a/tests/lib/Files/FilesystemTest.php b/tests/lib/Files/FilesystemTest.php index 4ab0456a810..a819acb1620 100644 --- a/tests/lib/Files/FilesystemTest.php +++ b/tests/lib/Files/FilesystemTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,21 +8,30 @@ namespace Test\Files; +use OC\Files\Filesystem; use OC\Files\Mount\MountPoint; use OC\Files\Storage\Temporary; +use OC\Files\View; use OC\User\NoUserException; +use OCP\Files; use OCP\Files\Config\IMountProvider; +use OCP\Files\Config\IMountProviderCollection; +use OCP\Files\Mount\IMountPoint; use OCP\Files\Storage\IStorageFactory; +use OCP\IConfig; +use OCP\ITempManager; use OCP\IUser; +use OCP\IUserManager; +use OCP\IUserSession; +use OCP\Server; class DummyMountProvider implements IMountProvider { - private $mounts = []; - /** * @param array $mounts */ - public function __construct(array $mounts) { - $this->mounts = $mounts; + public function __construct( + private array $mounts, + ) { } /** @@ -29,7 +39,7 @@ class DummyMountProvider implements IMountProvider { * * @param IUser $user * @param IStorageFactory $loader - * @return \OCP\Files\Mount\IMountPoint[] + * @return IMountPoint[] */ public function getMountsForUser(IUser $user, IStorageFactory $loader) { return isset($this->mounts[$user->getUID()]) ? $this->mounts[$user->getUID()] : []; @@ -44,8 +54,8 @@ class DummyMountProvider implements IMountProvider { * @package Test\Files */ class FilesystemTest extends \Test\TestCase { - public const TEST_FILESYSTEM_USER1 = "test-filesystem-user1"; - public const TEST_FILESYSTEM_USER2 = "test-filesystem-user1"; + public const TEST_FILESYSTEM_USER1 = 'test-filesystem-user1'; + public const TEST_FILESYSTEM_USER2 = 'test-filesystem-user1'; /** * @var array tmpDirs @@ -56,7 +66,7 @@ class FilesystemTest extends \Test\TestCase { * @return array */ private function getStorageData() { - $dir = \OC::$server->getTempManager()->getTemporaryFolder(); + $dir = Server::get(ITempManager::class)->getTemporaryFolder(); $this->tmpDirs[] = $dir; return ['datadir' => $dir]; } @@ -66,13 +76,13 @@ class FilesystemTest extends \Test\TestCase { $userBackend = new \Test\Util\User\Dummy(); $userBackend->createUser(self::TEST_FILESYSTEM_USER1, self::TEST_FILESYSTEM_USER1); $userBackend->createUser(self::TEST_FILESYSTEM_USER2, self::TEST_FILESYSTEM_USER2); - \OC::$server->getUserManager()->registerBackend($userBackend); + Server::get(IUserManager::class)->registerBackend($userBackend); $this->loginAsUser(); } protected function tearDown(): void { foreach ($this->tmpDirs as $dir) { - \OC_Helper::rmdirr($dir); + Files::rmdirr($dir); } $this->logout(); @@ -80,25 +90,25 @@ class FilesystemTest extends \Test\TestCase { parent::tearDown(); } - public function testMount() { - \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', self::getStorageData(), '/'); - $this->assertEquals('/', \OC\Files\Filesystem::getMountPoint('/')); - $this->assertEquals('/', \OC\Files\Filesystem::getMountPoint('/some/folder')); - [, $internalPath] = \OC\Files\Filesystem::resolvePath('/'); + public function testMount(): void { + Filesystem::mount('\OC\Files\Storage\Local', self::getStorageData(), '/'); + $this->assertEquals('/', Filesystem::getMountPoint('/')); + $this->assertEquals('/', Filesystem::getMountPoint('/some/folder')); + [, $internalPath] = Filesystem::resolvePath('/'); $this->assertEquals('', $internalPath); - [, $internalPath] = \OC\Files\Filesystem::resolvePath('/some/folder'); + [, $internalPath] = Filesystem::resolvePath('/some/folder'); $this->assertEquals('some/folder', $internalPath); - \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', self::getStorageData(), '/some'); - $this->assertEquals('/', \OC\Files\Filesystem::getMountPoint('/')); - $this->assertEquals('/some/', \OC\Files\Filesystem::getMountPoint('/some/folder')); - $this->assertEquals('/some/', \OC\Files\Filesystem::getMountPoint('/some/')); - $this->assertEquals('/some/', \OC\Files\Filesystem::getMountPoint('/some')); - [, $internalPath] = \OC\Files\Filesystem::resolvePath('/some/folder'); + Filesystem::mount('\OC\Files\Storage\Local', self::getStorageData(), '/some'); + $this->assertEquals('/', Filesystem::getMountPoint('/')); + $this->assertEquals('/some/', Filesystem::getMountPoint('/some/folder')); + $this->assertEquals('/some/', Filesystem::getMountPoint('/some/')); + $this->assertEquals('/some/', Filesystem::getMountPoint('/some')); + [, $internalPath] = Filesystem::resolvePath('/some/folder'); $this->assertEquals('folder', $internalPath); } - public function normalizePathData() { + public static function normalizePathData(): array { return [ ['/', ''], ['/', '/'], @@ -192,14 +202,12 @@ class FilesystemTest extends \Test\TestCase { ]; } - /** - * @dataProvider normalizePathData - */ - public function testNormalizePath($expected, $path, $stripTrailingSlash = true) { - $this->assertEquals($expected, \OC\Files\Filesystem::normalizePath($path, $stripTrailingSlash)); + #[\PHPUnit\Framework\Attributes\DataProvider('normalizePathData')] + public function testNormalizePath($expected, $path, $stripTrailingSlash = true): void { + $this->assertEquals($expected, Filesystem::normalizePath($path, $stripTrailingSlash)); } - public function normalizePathKeepUnicodeData() { + public static function normalizePathKeepUnicodeData(): array { $nfdName = 'ümlaut'; $nfcName = 'ümlaut'; return [ @@ -210,22 +218,20 @@ class FilesystemTest extends \Test\TestCase { ]; } - /** - * @dataProvider normalizePathKeepUnicodeData - */ - public function testNormalizePathKeepUnicode($expected, $path, $keepUnicode = false) { - $this->assertEquals($expected, \OC\Files\Filesystem::normalizePath($path, true, false, $keepUnicode)); + #[\PHPUnit\Framework\Attributes\DataProvider('normalizePathKeepUnicodeData')] + public function testNormalizePathKeepUnicode($expected, $path, $keepUnicode = false): void { + $this->assertEquals($expected, Filesystem::normalizePath($path, true, false, $keepUnicode)); } - public function testNormalizePathKeepUnicodeCache() { + public function testNormalizePathKeepUnicodeCache(): void { $nfdName = 'ümlaut'; $nfcName = 'ümlaut'; // call in succession due to cache - $this->assertEquals('/' . $nfcName, \OC\Files\Filesystem::normalizePath($nfdName, true, false, false)); - $this->assertEquals('/' . $nfdName, \OC\Files\Filesystem::normalizePath($nfdName, true, false, true)); + $this->assertEquals('/' . $nfcName, Filesystem::normalizePath($nfdName, true, false, false)); + $this->assertEquals('/' . $nfdName, Filesystem::normalizePath($nfdName, true, false, true)); } - public function isValidPathData() { + public static function isValidPathData(): array { return [ ['/', true], ['/path', true], @@ -251,14 +257,12 @@ class FilesystemTest extends \Test\TestCase { ]; } - /** - * @dataProvider isValidPathData - */ - public function testIsValidPath($path, $expected) { - $this->assertSame($expected, \OC\Files\Filesystem::isValidPath($path)); + #[\PHPUnit\Framework\Attributes\DataProvider('isValidPathData')] + public function testIsValidPath($path, $expected): void { + $this->assertSame($expected, Filesystem::isValidPath($path)); } - public function isFileBlacklistedData() { + public static function isFileBlacklistedData(): array { return [ ['/etc/foo/bar/foo.txt', false], ['\etc\foo/bar\foo.txt', false], @@ -273,48 +277,46 @@ class FilesystemTest extends \Test\TestCase { ]; } - /** - * @dataProvider isFileBlacklistedData - */ - public function testIsFileBlacklisted($path, $expected) { - $this->assertSame($expected, \OC\Files\Filesystem::isFileBlacklisted($path)); + #[\PHPUnit\Framework\Attributes\DataProvider('isFileBlacklistedData')] + public function testIsFileBlacklisted($path, $expected): void { + $this->assertSame($expected, Filesystem::isFileBlacklisted($path)); } - public function testNormalizePathUTF8() { + public function testNormalizePathUTF8(): void { if (!class_exists('Patchwork\PHP\Shim\Normalizer')) { $this->markTestSkipped('UTF8 normalizer Patchwork was not found'); } - $this->assertEquals("/foo/bar\xC3\xBC", \OC\Files\Filesystem::normalizePath("/foo/baru\xCC\x88")); - $this->assertEquals("/foo/bar\xC3\xBC", \OC\Files\Filesystem::normalizePath("\\foo\\baru\xCC\x88")); + $this->assertEquals("/foo/bar\xC3\xBC", Filesystem::normalizePath("/foo/baru\xCC\x88")); + $this->assertEquals("/foo/bar\xC3\xBC", Filesystem::normalizePath("\\foo\\baru\xCC\x88")); } - public function testHooks() { - if (\OC\Files\Filesystem::getView()) { + public function testHooks(): void { + if (Filesystem::getView()) { $user = \OC_User::getUser(); } else { $user = self::TEST_FILESYSTEM_USER1; $backend = new \Test\Util\User\Dummy(); - \OC_User::useBackend($backend); + Server::get(IUserManager::class)->registerBackend($backend); $backend->createUser($user, $user); - $userObj = \OC::$server->getUserManager()->get($user); - \OC::$server->getUserSession()->setUser($userObj); - \OC\Files\Filesystem::init($user, '/' . $user . '/files'); + $userObj = Server::get(IUserManager::class)->get($user); + Server::get(IUserSession::class)->setUser($userObj); + Filesystem::init($user, '/' . $user . '/files'); } \OC_Hook::clear('OC_Filesystem'); \OC_Hook::connect('OC_Filesystem', 'post_write', $this, 'dummyHook'); - \OC\Files\Filesystem::mount('OC\Files\Storage\Temporary', [], '/'); + Filesystem::mount('OC\Files\Storage\Temporary', [], '/'); - $rootView = new \OC\Files\View(''); + $rootView = new View(''); $rootView->mkdir('/' . $user); $rootView->mkdir('/' . $user . '/files'); // \OC\Files\Filesystem::file_put_contents('/foo', 'foo'); - \OC\Files\Filesystem::mkdir('/bar'); + Filesystem::mkdir('/bar'); // \OC\Files\Filesystem::file_put_contents('/bar//foo', 'foo'); - $tmpFile = \OC::$server->getTempManager()->getTemporaryFile(); + $tmpFile = Server::get(ITempManager::class)->getTemporaryFile(); file_put_contents($tmpFile, 'foo'); $fh = fopen($tmpFile, 'r'); // \OC\Files\Filesystem::file_put_contents('/bar//foo', $fh); @@ -324,30 +326,30 @@ class FilesystemTest extends \Test\TestCase { * Tests that an exception is thrown when passed user does not exist. * */ - public function testLocalMountWhenUserDoesNotExist() { - $this->expectException(\OC\User\NoUserException::class); + public function testLocalMountWhenUserDoesNotExist(): void { + $this->expectException(NoUserException::class); $userId = $this->getUniqueID('user_'); - \OC\Files\Filesystem::initMountPoints($userId); + Filesystem::initMountPoints($userId); } - public function testNullUserThrows() { - $this->expectException(\OC\User\NoUserException::class); + public function testNullUserThrows(): void { + $this->expectException(NoUserException::class); - \OC\Files\Filesystem::initMountPoints(null); + Filesystem::initMountPoints(null); } - public function testNullUserThrowsTwice() { + public function testNullUserThrowsTwice(): void { $thrown = 0; try { - \OC\Files\Filesystem::initMountPoints(null); + Filesystem::initMountPoints(null); } catch (NoUserException $e) { $thrown++; } try { - \OC\Files\Filesystem::initMountPoints(null); + Filesystem::initMountPoints(null); } catch (NoUserException $e) { $thrown++; } @@ -357,18 +359,18 @@ class FilesystemTest extends \Test\TestCase { /** * Tests that an exception is thrown when passed user does not exist. */ - public function testLocalMountWhenUserDoesNotExistTwice() { + public function testLocalMountWhenUserDoesNotExistTwice(): void { $thrown = 0; $userId = $this->getUniqueID('user_'); try { - \OC\Files\Filesystem::initMountPoints($userId); + Filesystem::initMountPoints($userId); } catch (NoUserException $e) { $thrown++; } try { - \OC\Files\Filesystem::initMountPoints($userId); + Filesystem::initMountPoints($userId); } catch (NoUserException $e) { $thrown++; } @@ -379,14 +381,14 @@ class FilesystemTest extends \Test\TestCase { /** * Tests that the home storage is used for the user's mount point */ - public function testHomeMount() { + public function testHomeMount(): void { $userId = $this->getUniqueID('user_'); - \OC::$server->getUserManager()->createUser($userId, $userId); + Server::get(IUserManager::class)->createUser($userId, $userId); - \OC\Files\Filesystem::initMountPoints($userId); + Filesystem::initMountPoints($userId); - $homeMount = \OC\Files\Filesystem::getStorage('/' . $userId . '/'); + $homeMount = Filesystem::getStorage('/' . $userId . '/'); $this->assertTrue($homeMount->instanceOfStorage('\OCP\Files\IHomeStorage')); if ($homeMount->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage')) { @@ -395,7 +397,7 @@ class FilesystemTest extends \Test\TestCase { $this->assertEquals('home::' . $userId, $homeMount->getId()); } - $user = \OC::$server->getUserManager()->get($userId); + $user = Server::get(IUserManager::class)->get($userId); if ($user !== null) { $user->delete(); } @@ -403,30 +405,30 @@ class FilesystemTest extends \Test\TestCase { public function dummyHook($arguments) { $path = $arguments['path']; - $this->assertEquals($path, \OC\Files\Filesystem::normalizePath($path)); //the path passed to the hook should already be normalized + $this->assertEquals($path, Filesystem::normalizePath($path)); //the path passed to the hook should already be normalized } /** * Test that the default cache dir is part of the user's home */ - public function testMountDefaultCacheDir() { + public function testMountDefaultCacheDir(): void { $userId = $this->getUniqueID('user_'); - $config = \OC::$server->getConfig(); + $config = Server::get(IConfig::class); $oldCachePath = $config->getSystemValueString('cache_path', ''); // no cache path configured $config->setSystemValue('cache_path', ''); - \OC::$server->getUserManager()->createUser($userId, $userId); - \OC\Files\Filesystem::initMountPoints($userId); + Server::get(IUserManager::class)->createUser($userId, $userId); + Filesystem::initMountPoints($userId); $this->assertEquals( '/' . $userId . '/', - \OC\Files\Filesystem::getMountPoint('/' . $userId . '/cache') + Filesystem::getMountPoint('/' . $userId . '/cache') ); - [$storage, $internalPath] = \OC\Files\Filesystem::resolvePath('/' . $userId . '/cache'); + [$storage, $internalPath] = Filesystem::resolvePath('/' . $userId . '/cache'); $this->assertTrue($storage->instanceOfStorage('\OCP\Files\IHomeStorage')); $this->assertEquals('cache', $internalPath); - $user = \OC::$server->getUserManager()->get($userId); + $user = Server::get(IUserManager::class)->get($userId); if ($user !== null) { $user->delete(); } @@ -438,26 +440,26 @@ class FilesystemTest extends \Test\TestCase { * Test that an external cache is mounted into * the user's home */ - public function testMountExternalCacheDir() { + public function testMountExternalCacheDir(): void { $userId = $this->getUniqueID('user_'); - $config = \OC::$server->getConfig(); + $config = Server::get(IConfig::class); $oldCachePath = $config->getSystemValueString('cache_path', ''); // set cache path to temp dir - $cachePath = \OC::$server->getTempManager()->getTemporaryFolder() . '/extcache'; + $cachePath = Server::get(ITempManager::class)->getTemporaryFolder() . '/extcache'; $config->setSystemValue('cache_path', $cachePath); - \OC::$server->getUserManager()->createUser($userId, $userId); - \OC\Files\Filesystem::initMountPoints($userId); + Server::get(IUserManager::class)->createUser($userId, $userId); + Filesystem::initMountPoints($userId); $this->assertEquals( '/' . $userId . '/cache/', - \OC\Files\Filesystem::getMountPoint('/' . $userId . '/cache') + Filesystem::getMountPoint('/' . $userId . '/cache') ); - [$storage, $internalPath] = \OC\Files\Filesystem::resolvePath('/' . $userId . '/cache'); + [$storage, $internalPath] = Filesystem::resolvePath('/' . $userId . '/cache'); $this->assertTrue($storage->instanceOfStorage('\OC\Files\Storage\Local')); $this->assertEquals('', $internalPath); - $user = \OC::$server->getUserManager()->get($userId); + $user = Server::get(IUserManager::class)->get($userId); if ($user !== null) { $user->delete(); } @@ -465,12 +467,12 @@ class FilesystemTest extends \Test\TestCase { $config->setSystemValue('cache_path', $oldCachePath); } - public function testRegisterMountProviderAfterSetup() { - \OC\Files\Filesystem::initMountPoints(self::TEST_FILESYSTEM_USER2); - $this->assertEquals('/', \OC\Files\Filesystem::getMountPoint('/foo/bar')); + public function testRegisterMountProviderAfterSetup(): void { + Filesystem::initMountPoints(self::TEST_FILESYSTEM_USER2); + $this->assertEquals('/', Filesystem::getMountPoint('/foo/bar')); $mount = new MountPoint(new Temporary([]), '/foo/bar'); $mountProvider = new DummyMountProvider([self::TEST_FILESYSTEM_USER2 => [$mount]]); - \OC::$server->getMountProviderCollection()->registerProvider($mountProvider); - $this->assertEquals('/foo/bar/', \OC\Files\Filesystem::getMountPoint('/foo/bar')); + Server::get(IMountProviderCollection::class)->registerProvider($mountProvider); + $this->assertEquals('/foo/bar/', Filesystem::getMountPoint('/foo/bar')); } } diff --git a/tests/lib/Files/Mount/ManagerTest.php b/tests/lib/Files/Mount/ManagerTest.php index f8adb2bf1cf..e6cf3348664 100644 --- a/tests/lib/Files/Mount/ManagerTest.php +++ b/tests/lib/Files/Mount/ManagerTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,11 +8,12 @@ namespace Test\Files\Mount; +use OC\Files\Mount\MountPoint; use OC\Files\SetupManagerFactory; use OC\Files\Storage\Temporary; class LongId extends Temporary { - public function getId() { + public function getId(): string { return 'long:' . str_repeat('foo', 50) . parent::getId(); } } @@ -27,34 +29,34 @@ class ManagerTest extends \Test\TestCase { $this->manager = new \OC\Files\Mount\Manager($this->createMock(SetupManagerFactory::class)); } - public function testFind() { - $rootMount = new \OC\Files\Mount\MountPoint(new Temporary([]), '/'); + public function testFind(): void { + $rootMount = new MountPoint(new Temporary([]), '/'); $this->manager->addMount($rootMount); $this->assertEquals($rootMount, $this->manager->find('/')); $this->assertEquals($rootMount, $this->manager->find('/foo/bar')); $storage = new Temporary([]); - $mount1 = new \OC\Files\Mount\MountPoint($storage, '/foo'); + $mount1 = new MountPoint($storage, '/foo'); $this->manager->addMount($mount1); $this->assertEquals($rootMount, $this->manager->find('/')); $this->assertEquals($mount1, $this->manager->find('/foo/bar')); $this->assertEquals(1, count($this->manager->findIn('/'))); - $mount2 = new \OC\Files\Mount\MountPoint(new Temporary([]), '/bar'); + $mount2 = new MountPoint(new Temporary([]), '/bar'); $this->manager->addMount($mount2); $this->assertEquals(2, count($this->manager->findIn('/'))); $id = $mount1->getStorageId(); $this->assertEquals([$mount1], $this->manager->findByStorageId($id)); - $mount3 = new \OC\Files\Mount\MountPoint($storage, '/foo/bar'); + $mount3 = new MountPoint($storage, '/foo/bar'); $this->manager->addMount($mount3); $this->assertEquals([$mount1, $mount3], $this->manager->findByStorageId($id)); } - public function testLong() { + public function testLong(): void { $storage = new LongId([]); - $mount = new \OC\Files\Mount\MountPoint($storage, '/foo'); + $mount = new MountPoint($storage, '/foo'); $this->manager->addMount($mount); $id = $mount->getStorageId(); diff --git a/tests/lib/Files/Mount/MountPointTest.php b/tests/lib/Files/Mount/MountPointTest.php index 189667df276..bcbcc96e3a3 100644 --- a/tests/lib/Files/Mount/MountPointTest.php +++ b/tests/lib/Files/Mount/MountPointTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,15 +8,14 @@ namespace Test\Files\Mount; +use OC\Files\Mount\MountPoint; use OC\Files\Storage\StorageFactory; -use OCP\Files\Storage; - -class DummyStorage { -} +use OC\Lockdown\Filesystem\NullStorage; +use OCP\Files\Storage\IStorage; class MountPointTest extends \Test\TestCase { - public function testGetStorage() { - $storage = $this->createMock(Storage::class); + public function testGetStorage(): void { + $storage = $this->createMock(IStorage::class); $storage->expects($this->once()) ->method('getId') ->willReturn(123); @@ -25,9 +25,9 @@ class MountPointTest extends \Test\TestCase { ->method('wrap') ->willReturn($storage); - $mountPoint = new \OC\Files\Mount\MountPoint( + $mountPoint = new MountPoint( // just use this because a real class is needed - '\Test\Files\Mount\DummyStorage', + NullStorage::class, '/mountpoint', null, $loader @@ -41,20 +41,20 @@ class MountPointTest extends \Test\TestCase { $this->assertEquals('/another/', $mountPoint->getMountPoint()); } - public function testInvalidStorage() { + public function testInvalidStorage(): void { $loader = $this->createMock(StorageFactory::class); $loader->expects($this->once()) ->method('wrap') - ->will($this->throwException(new \Exception('Test storage init exception'))); + ->willThrowException(new \Exception('Test storage init exception')); $called = false; - $wrapper = function ($mountPoint, $storage) use ($called) { + $wrapper = function ($mountPoint, $storage) use ($called): void { $called = true; }; - $mountPoint = new \OC\Files\Mount\MountPoint( + $mountPoint = new MountPoint( // just use this because a real class is needed - '\Test\Files\Mount\DummyStorage', + NullStorage::class, '/mountpoint', null, $loader diff --git a/tests/lib/Files/Mount/MountTest.php b/tests/lib/Files/Mount/MountTest.php index 0b4c6a214f3..05c8a7d58e7 100644 --- a/tests/lib/Files/Mount/MountTest.php +++ b/tests/lib/Files/Mount/MountTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2020-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,24 +8,25 @@ namespace Test\Files\Mount; +use OC\Files\Mount\MountPoint; use OC\Files\Storage\StorageFactory; use OC\Files\Storage\Wrapper\Wrapper; class MountTest extends \Test\TestCase { - public function testFromStorageObject() { + public function testFromStorageObject(): void { $storage = $this->getMockBuilder('\OC\Files\Storage\Temporary') ->disableOriginalConstructor() ->getMock(); - $mount = new \OC\Files\Mount\MountPoint($storage, '/foo'); + $mount = new MountPoint($storage, '/foo'); $this->assertInstanceOf('\OC\Files\Storage\Temporary', $mount->getStorage()); } - public function testFromStorageClassname() { - $mount = new \OC\Files\Mount\MountPoint('\OC\Files\Storage\Temporary', '/foo'); + public function testFromStorageClassname(): void { + $mount = new MountPoint('\OC\Files\Storage\Temporary', '/foo'); $this->assertInstanceOf('\OC\Files\Storage\Temporary', $mount->getStorage()); } - public function testWrapper() { + public function testWrapper(): void { $test = $this; $wrapper = function ($mountPoint, $storage) use (&$test) { $test->assertEquals('/foo/', $mountPoint); @@ -38,7 +40,7 @@ class MountTest extends \Test\TestCase { $storage = $this->getMockBuilder('\OC\Files\Storage\Temporary') ->disableOriginalConstructor() ->getMock(); - $mount = new \OC\Files\Mount\MountPoint($storage, '/foo', [], $loader); + $mount = new MountPoint($storage, '/foo', [], $loader); $this->assertInstanceOf('\OC\Files\Storage\Wrapper\Wrapper', $mount->getStorage()); } } diff --git a/tests/lib/Files/Mount/ObjectHomeMountProviderTest.php b/tests/lib/Files/Mount/ObjectHomeMountProviderTest.php index 9b6aaeccfeb..ae0a53f2cc0 100644 --- a/tests/lib/Files/Mount/ObjectHomeMountProviderTest.php +++ b/tests/lib/Files/Mount/ObjectHomeMountProviderTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,6 +8,9 @@ namespace Test\Files\Mount; use OC\Files\Mount\ObjectHomeMountProvider; +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; +use OCP\App\IAppManager; +use OCP\Files\ObjectStore\IObjectStore; use OCP\Files\Storage\IStorageFactory; use OCP\IConfig; use OCP\IUser; @@ -31,53 +35,56 @@ class ObjectHomeMountProviderTest extends \Test\TestCase { $this->user = $this->createMock(IUser::class); $this->loader = $this->createMock(IStorageFactory::class); - $this->provider = new ObjectHomeMountProvider($this->config); + $objectStoreConfig = new PrimaryObjectStoreConfig($this->config, $this->createMock(IAppManager::class)); + $this->provider = new ObjectHomeMountProvider($objectStoreConfig); } - public function testSingleBucket() { - $this->config->expects($this->once()) - ->method('getSystemValue') - ->with($this->equalTo('objectstore'), '') - ->willReturn([ - 'class' => 'Test\Files\Mount\FakeObjectStore', - ]); + public function testSingleBucket(): void { + $this->config->method('getSystemValue') + ->willReturnCallback(function ($key, $default) { + if ($key === 'objectstore') { + return [ + 'class' => 'Test\Files\Mount\FakeObjectStore', + 'arguments' => [ + 'foo' => 'bar' + ], + ]; + } else { + return $default; + } + }); - $this->user->expects($this->never())->method($this->anything()); - $this->loader->expects($this->never())->method($this->anything()); - - $config = $this->invokePrivate($this->provider, 'getSingleBucketObjectStoreConfig', [$this->user, $this->loader]); + $mount = $this->provider->getHomeMountForUser($this->user, $this->loader); + $arguments = $this->invokePrivate($mount, 'arguments'); - $this->assertArrayHasKey('class', $config); - $this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore'); - $this->assertArrayHasKey('arguments', $config); - $this->assertArrayHasKey('user', $config['arguments']); - $this->assertSame($this->user, $config['arguments']['user']); - $this->assertArrayHasKey('objectstore', $config['arguments']); - $this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']); + $objectStore = $arguments['objectstore']; + $this->assertInstanceOf(FakeObjectStore::class, $objectStore); + $this->assertEquals(['foo' => 'bar', 'multibucket' => false], $objectStore->getArguments()); } - public function testMultiBucket() { - $this->config->expects($this->exactly(2)) - ->method('getSystemValue') - ->with($this->equalTo('objectstore_multibucket'), '') - ->willReturn([ - 'class' => 'Test\Files\Mount\FakeObjectStore', - ]); + public function testMultiBucket(): void { + $this->config->method('getSystemValue') + ->willReturnCallback(function ($key, $default) { + if ($key === 'objectstore_multibucket') { + return [ + 'class' => 'Test\Files\Mount\FakeObjectStore', + 'arguments' => [ + 'foo' => 'bar' + ], + ]; + } else { + return $default; + } + }); $this->user->method('getUID') ->willReturn('uid'); $this->loader->expects($this->never())->method($this->anything()); - $this->config->expects($this->once()) - ->method('getUserValue') - ->with( - $this->equalTo('uid'), - $this->equalTo('homeobjectstore'), - $this->equalTo('bucket'), - $this->equalTo(null) - )->willReturn(null); + $this->config->method('getUserValue') + ->willReturn(null); - $this->config->expects($this->once()) + $this->config ->method('setUserValue') ->with( $this->equalTo('uid'), @@ -87,42 +94,37 @@ class ObjectHomeMountProviderTest extends \Test\TestCase { $this->equalTo(null) ); - $config = $this->invokePrivate($this->provider, 'getMultiBucketObjectStoreConfig', [$this->user, $this->loader]); - - $this->assertArrayHasKey('class', $config); - $this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore'); - $this->assertArrayHasKey('arguments', $config); - $this->assertArrayHasKey('user', $config['arguments']); - $this->assertSame($this->user, $config['arguments']['user']); - $this->assertArrayHasKey('objectstore', $config['arguments']); - $this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']); - $this->assertArrayHasKey('bucket', $config['arguments']); - $this->assertEquals('49', $config['arguments']['bucket']); - } - - public function testMultiBucketWithPrefix() { - $this->config->expects($this->exactly(2)) - ->method('getSystemValue') - ->with('objectstore_multibucket') - ->willReturn([ - 'class' => 'Test\Files\Mount\FakeObjectStore', - 'arguments' => [ - 'bucket' => 'myBucketPrefix', - ], - ]); + $mount = $this->provider->getHomeMountForUser($this->user, $this->loader); + $arguments = $this->invokePrivate($mount, 'arguments'); + + $objectStore = $arguments['objectstore']; + $this->assertInstanceOf(FakeObjectStore::class, $objectStore); + $this->assertEquals(['foo' => 'bar', 'bucket' => 49, 'multibucket' => true], $objectStore->getArguments()); + } + + public function testMultiBucketWithPrefix(): void { + $this->config->method('getSystemValue') + ->willReturnCallback(function ($key, $default) { + if ($key === 'objectstore_multibucket') { + return [ + 'class' => 'Test\Files\Mount\FakeObjectStore', + 'arguments' => [ + 'foo' => 'bar', + 'bucket' => 'myBucketPrefix', + ], + ]; + } else { + return $default; + } + }); $this->user->method('getUID') ->willReturn('uid'); $this->loader->expects($this->never())->method($this->anything()); - $this->config->expects($this->once()) + $this->config ->method('getUserValue') - ->with( - $this->equalTo('uid'), - $this->equalTo('homeobjectstore'), - $this->equalTo('bucket'), - $this->equalTo(null) - )->willReturn(null); + ->willReturn(null); $this->config->expects($this->once()) ->method('setUserValue') @@ -134,66 +136,70 @@ class ObjectHomeMountProviderTest extends \Test\TestCase { $this->equalTo(null) ); - $config = $this->invokePrivate($this->provider, 'getMultiBucketObjectStoreConfig', [$this->user, $this->loader]); + $mount = $this->provider->getHomeMountForUser($this->user, $this->loader); + $arguments = $this->invokePrivate($mount, 'arguments'); - $this->assertArrayHasKey('class', $config); - $this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore'); - $this->assertArrayHasKey('arguments', $config); - $this->assertArrayHasKey('user', $config['arguments']); - $this->assertSame($this->user, $config['arguments']['user']); - $this->assertArrayHasKey('objectstore', $config['arguments']); - $this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']); - $this->assertArrayHasKey('bucket', $config['arguments']); - $this->assertEquals('myBucketPrefix49', $config['arguments']['bucket']); + $objectStore = $arguments['objectstore']; + $this->assertInstanceOf(FakeObjectStore::class, $objectStore); + $this->assertEquals(['foo' => 'bar', 'bucket' => 'myBucketPrefix49', 'multibucket' => true], $objectStore->getArguments()); } - public function testMultiBucketBucketAlreadySet() { - $this->config->expects($this->once()) - ->method('getSystemValue') - ->with('objectstore_multibucket') - ->willReturn([ - 'class' => 'Test\Files\Mount\FakeObjectStore', - 'arguments' => [ - 'bucket' => 'myBucketPrefix', - ], - ]); + public function testMultiBucketBucketAlreadySet(): void { + $this->config->method('getSystemValue') + ->willReturnCallback(function ($key, $default) { + if ($key === 'objectstore_multibucket') { + return [ + 'class' => 'Test\Files\Mount\FakeObjectStore', + 'arguments' => [ + 'foo' => 'bar', + 'bucket' => 'myBucketPrefix', + ], + ]; + } else { + return $default; + } + }); $this->user->method('getUID') ->willReturn('uid'); $this->loader->expects($this->never())->method($this->anything()); - $this->config->expects($this->once()) + $this->config ->method('getUserValue') - ->with( - $this->equalTo('uid'), - $this->equalTo('homeobjectstore'), - $this->equalTo('bucket'), - $this->equalTo(null) - )->willReturn('awesomeBucket1'); + ->willReturnCallback(function ($uid, $app, $key, $default) { + if ($uid === 'uid' && $app === 'homeobjectstore' && $key === 'bucket') { + return 'awesomeBucket1'; + } else { + return $default; + } + }); $this->config->expects($this->never()) ->method('setUserValue'); - $config = $this->invokePrivate($this->provider, 'getMultiBucketObjectStoreConfig', [$this->user, $this->loader]); - - $this->assertArrayHasKey('class', $config); - $this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore'); - $this->assertArrayHasKey('arguments', $config); - $this->assertArrayHasKey('user', $config['arguments']); - $this->assertSame($this->user, $config['arguments']['user']); - $this->assertArrayHasKey('objectstore', $config['arguments']); - $this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']); - $this->assertArrayHasKey('bucket', $config['arguments']); - $this->assertEquals('awesomeBucket1', $config['arguments']['bucket']); - } - - public function testMultiBucketConfigFirst() { - $this->config->expects($this->exactly(2)) - ->method('getSystemValue') - ->with('objectstore_multibucket') - ->willReturn([ - 'class' => 'Test\Files\Mount\FakeObjectStore', - ]); + $mount = $this->provider->getHomeMountForUser($this->user, $this->loader); + $arguments = $this->invokePrivate($mount, 'arguments'); + + $objectStore = $arguments['objectstore']; + $this->assertInstanceOf(FakeObjectStore::class, $objectStore); + $this->assertEquals(['foo' => 'bar', 'bucket' => 'awesomeBucket1', 'multibucket' => true], $objectStore->getArguments()); + } + + public function testMultiBucketConfigFirst(): void { + $this->config->method('getSystemValue') + ->willReturnCallback(function ($key, $default) { + if ($key === 'objectstore_multibucket') { + return [ + 'class' => 'Test\Files\Mount\FakeObjectStore', + 'arguments' => [ + 'foo' => 'bar', + 'bucket' => 'myBucketPrefix', + ], + ]; + } else { + return $default; + } + }); $this->user->method('getUID') ->willReturn('uid'); @@ -203,18 +209,18 @@ class ObjectHomeMountProviderTest extends \Test\TestCase { $this->assertInstanceOf('OC\Files\Mount\MountPoint', $mount); } - public function testMultiBucketConfigFirstFallBackSingle() { - $this->config->expects($this->exactly(2)) - ->method('getSystemValue') - ->withConsecutive( - [$this->equalTo('objectstore_multibucket')], - [$this->equalTo('objectstore')], - )->willReturnOnConsecutiveCalls( - '', - [ + public function testMultiBucketConfigFirstFallBackSingle(): void { + $this->config + ->method('getSystemValue')->willReturnMap([ + ['objectstore_multibucket', null, null], + ['objectstore', null, [ 'class' => 'Test\Files\Mount\FakeObjectStore', - ], - ); + 'arguments' => [ + 'foo' => 'bar', + 'bucket' => 'myBucketPrefix', + ], + ]], + ]); $this->user->method('getUID') ->willReturn('uid'); @@ -224,24 +230,42 @@ class ObjectHomeMountProviderTest extends \Test\TestCase { $this->assertInstanceOf('OC\Files\Mount\MountPoint', $mount); } - public function testNoObjectStore() { - $this->config->expects($this->exactly(2)) - ->method('getSystemValue') - ->willReturn(''); + public function testNoObjectStore(): void { + $this->config->method('getSystemValue') + ->willReturnCallback(function ($key, $default) { + return $default; + }); $mount = $this->provider->getHomeMountForUser($this->user, $this->loader); $this->assertNull($mount); } } -class FakeObjectStore { - private $arguments; - - public function __construct(array $arguments) { - $this->arguments = $arguments; +class FakeObjectStore implements IObjectStore { + public function __construct( + private array $arguments, + ) { } public function getArguments() { return $this->arguments; } + + public function getStorageId() { + } + + public function readObject($urn) { + } + + public function writeObject($urn, $stream, ?string $mimetype = null) { + } + + public function deleteObject($urn) { + } + + public function objectExists($urn) { + } + + public function copyObject($from, $to) { + } } diff --git a/tests/lib/Files/Mount/ObjectStorePreviewCacheMountProviderTest.php b/tests/lib/Files/Mount/ObjectStorePreviewCacheMountProviderTest.php index b22224aa7db..9060bf0d5f5 100644 --- a/tests/lib/Files/Mount/ObjectStorePreviewCacheMountProviderTest.php +++ b/tests/lib/Files/Mount/ObjectStorePreviewCacheMountProviderTest.php @@ -43,7 +43,7 @@ class ObjectStorePreviewCacheMountProviderTest extends \Test\TestCase { $this->provider = new ObjectStorePreviewCacheMountProvider($this->logger, $this->config); } - public function testNoMultibucketObjectStorage() { + public function testNoMultibucketObjectStorage(): void { $this->config->expects($this->once()) ->method('getSystemValue') ->with('objectstore_multibucket') @@ -52,7 +52,7 @@ class ObjectStorePreviewCacheMountProviderTest extends \Test\TestCase { $this->assertEquals([], $this->provider->getRootMounts($this->loader)); } - public function testMultibucketObjectStorage() { + public function testMultibucketObjectStorage(): void { $objectstoreConfig = [ 'class' => S3::class, 'arguments' => [ diff --git a/tests/lib/Files/Mount/RootMountProviderTest.php b/tests/lib/Files/Mount/RootMountProviderTest.php index 4a5048d2863..bf29bfa070a 100644 --- a/tests/lib/Files/Mount/RootMountProviderTest.php +++ b/tests/lib/Files/Mount/RootMountProviderTest.php @@ -10,11 +10,12 @@ namespace Test\Files\Mount; use OC\Files\Mount\RootMountProvider; use OC\Files\ObjectStore\ObjectStoreStorage; +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; use OC\Files\ObjectStore\S3; use OC\Files\Storage\LocalRootStorage; use OC\Files\Storage\StorageFactory; +use OCP\App\IAppManager; use OCP\IConfig; -use Psr\Log\LoggerInterface; use Test\TestCase; /** @@ -40,11 +41,11 @@ class RootMountProviderTest extends TestCase { private function getProvider(array $systemConfig): RootMountProvider { $config = $this->getConfig($systemConfig); - $provider = new RootMountProvider($config, $this->createMock(LoggerInterface::class)); - return $provider; + $objectStoreConfig = new PrimaryObjectStoreConfig($config, $this->createMock(IAppManager::class)); + return new RootMountProvider($objectStoreConfig, $config); } - public function testLocal() { + public function testLocal(): void { $provider = $this->getProvider([ 'datadirectory' => '/data', ]); @@ -58,20 +59,20 @@ class RootMountProviderTest extends TestCase { $this->assertEquals('/data/', $storage->getSourcePath('')); } - public function testObjectStore() { + public function testObjectStore(): void { $provider = $this->getProvider([ 'objectstore' => [ - "class" => "OC\Files\ObjectStore\S3", - "arguments" => [ - "bucket" => "nextcloud", - "autocreate" => true, - "key" => "minio", - "secret" => "minio123", - "hostname" => "localhost", - "port" => 9000, - "use_ssl" => false, - "use_path_style" => true, - "uploadPartSize" => 52428800, + 'class' => "OC\Files\ObjectStore\S3", + 'arguments' => [ + 'bucket' => 'nextcloud', + 'autocreate' => true, + 'key' => 'minio', + 'secret' => 'minio123', + 'hostname' => 'localhost', + 'port' => 9000, + 'use_ssl' => false, + 'use_path_style' => true, + 'uploadPartSize' => 52428800, ], ], ]); @@ -91,20 +92,20 @@ class RootMountProviderTest extends TestCase { $this->assertEquals('nextcloud', $objectStore->getBucket()); } - public function testObjectStoreMultiBucket() { + public function testObjectStoreMultiBucket(): void { $provider = $this->getProvider([ 'objectstore_multibucket' => [ - "class" => "OC\Files\ObjectStore\S3", - "arguments" => [ - "bucket" => "nextcloud", - "autocreate" => true, - "key" => "minio", - "secret" => "minio123", - "hostname" => "localhost", - "port" => 9000, - "use_ssl" => false, - "use_path_style" => true, - "uploadPartSize" => 52428800, + 'class' => "OC\Files\ObjectStore\S3", + 'arguments' => [ + 'bucket' => 'nextcloud', + 'autocreate' => true, + 'key' => 'minio', + 'secret' => 'minio123', + 'hostname' => 'localhost', + 'port' => 9000, + 'use_ssl' => false, + 'use_path_style' => true, + 'uploadPartSize' => 52428800, ], ], ]); diff --git a/tests/lib/Files/Node/FileTest.php b/tests/lib/Files/Node/FileTest.php index 35c2443aeff..eec34d156ad 100644 --- a/tests/lib/Files/Node/FileTest.php +++ b/tests/lib/Files/Node/FileTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,6 +8,11 @@ namespace Test\Files\Node; +use OC\Files\Node\File; +use OC\Files\Node\Root; +use OCP\Constants; +use OCP\Files\NotPermittedException; + /** * Class FileTest * @@ -14,12 +20,12 @@ namespace Test\Files\Node; * * @package Test\Files\Node */ -class FileTest extends NodeTest { +class FileTest extends NodeTestCase { protected function createTestNode($root, $view, $path, array $data = [], $internalPath = '', $storage = null) { if ($data || $internalPath || $storage) { - return new \OC\Files\Node\File($root, $view, $path, $this->getFileInfo($data, $internalPath, $storage)); + return new File($root, $view, $path, $this->getFileInfo($data, $internalPath, $storage)); } else { - return new \OC\Files\Node\File($root, $view, $path); + return new File($root, $view, $path); } } @@ -35,13 +41,13 @@ class FileTest extends NodeTest { return 'unlink'; } - public function testGetContent() { + public function testGetContent(): void { /** @var \OC\Files\Node\Root|\PHPUnit\Framework\MockObject\MockObject $root */ - $root = $this->getMockBuilder('\OC\Files\Node\Root') + $root = $this->getMockBuilder(Root::class) ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); - $hook = function ($file) { + $hook = function ($file): void { throw new \Exception('Hooks are not supposed to be called'); }; @@ -56,18 +62,18 @@ class FileTest extends NodeTest { $this->view->expects($this->once()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_READ])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_READ])); - $node = new \OC\Files\Node\File($root, $this->view, '/bar/foo'); + $node = new File($root, $this->view, '/bar/foo'); $this->assertEquals('bar', $node->getContent()); } - public function testGetContentNotPermitted() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testGetContentNotPermitted(): void { + $this->expectException(NotPermittedException::class); /** @var \OC\Files\Node\Root|\PHPUnit\Framework\MockObject\MockObject $root */ - $root = $this->getMockBuilder('\OC\Files\Node\Root') + $root = $this->getMockBuilder(Root::class) ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); @@ -80,13 +86,13 @@ class FileTest extends NodeTest { ->with('/bar/foo') ->willReturn($this->getFileInfo(['permissions' => 0])); - $node = new \OC\Files\Node\File($root, $this->view, '/bar/foo'); + $node = new File($root, $this->view, '/bar/foo'); $node->getContent(); } - public function testPutContent() { + public function testPutContent(): void { /** @var \OC\Files\Node\Root|\PHPUnit\Framework\MockObject\MockObject $root */ - $root = $this->getMockBuilder('\OC\Files\Node\Root') + $root = $this->getMockBuilder(Root::class) ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); @@ -97,38 +103,38 @@ class FileTest extends NodeTest { $this->view->expects($this->once()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL])); $this->view->expects($this->once()) ->method('file_put_contents') ->with('/bar/foo', 'bar') ->willReturn(true); - $node = new \OC\Files\Node\File($root, $this->view, '/bar/foo'); + $node = new File($root, $this->view, '/bar/foo'); $node->putContent('bar'); } - public function testPutContentNotPermitted() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testPutContentNotPermitted(): void { + $this->expectException(NotPermittedException::class); /** @var \OC\Files\Node\Root|\PHPUnit\Framework\MockObject\MockObject $root */ - $root = $this->getMockBuilder('\OC\Files\Node\Root') + $root = $this->getMockBuilder(Root::class) ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); $this->view->expects($this->once()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_READ])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_READ])); - $node = new \OC\Files\Node\File($root, $this->view, '/bar/foo'); + $node = new File($root, $this->view, '/bar/foo'); $node->putContent('bar'); } - public function testGetMimeType() { + public function testGetMimeType(): void { /** @var \OC\Files\Node\Root|\PHPUnit\Framework\MockObject\MockObject $root */ - $root = $this->getMockBuilder('\OC\Files\Node\Root') + $root = $this->getMockBuilder(Root::class) ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); @@ -137,16 +143,16 @@ class FileTest extends NodeTest { ->with('/bar/foo') ->willReturn($this->getFileInfo(['mimetype' => 'text/plain'])); - $node = new \OC\Files\Node\File($root, $this->view, '/bar/foo'); + $node = new File($root, $this->view, '/bar/foo'); $this->assertEquals('text/plain', $node->getMimeType()); } - public function testFOpenRead() { + public function testFOpenRead(): void { $stream = fopen('php://memory', 'w+'); fwrite($stream, 'bar'); rewind($stream); - $root = new \OC\Files\Node\Root( + $root = new Root( $this->manager, $this->view, $this->user, @@ -157,7 +163,7 @@ class FileTest extends NodeTest { $this->cacheFactory, ); - $hook = function ($file) { + $hook = function ($file): void { throw new \Exception('Hooks are not supposed to be called'); }; @@ -172,18 +178,18 @@ class FileTest extends NodeTest { $this->view->expects($this->once()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL])); - $node = new \OC\Files\Node\File($root, $this->view, '/bar/foo'); + $node = new File($root, $this->view, '/bar/foo'); $fh = $node->fopen('r'); $this->assertEquals($stream, $fh); $this->assertEquals('bar', fread($fh, 3)); } - public function testFOpenWrite() { + public function testFOpenWrite(): void { $stream = fopen('php://memory', 'w+'); - $root = new \OC\Files\Node\Root( + $root = new Root( $this->manager, $this->view, $this->user, @@ -194,7 +200,7 @@ class FileTest extends NodeTest { $this->cacheFactory, ); $hooksCalled = 0; - $hook = function ($file) use (&$hooksCalled) { + $hook = function ($file) use (&$hooksCalled): void { $hooksCalled++; }; @@ -209,9 +215,9 @@ class FileTest extends NodeTest { $this->view->expects($this->once()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL])); - $node = new \OC\Files\Node\File($root, $this->view, '/bar/foo'); + $node = new File($root, $this->view, '/bar/foo'); $fh = $node->fopen('w'); $this->assertEquals($stream, $fh); fwrite($fh, 'bar'); @@ -221,10 +227,10 @@ class FileTest extends NodeTest { } - public function testFOpenReadNotPermitted() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testFOpenReadNotPermitted(): void { + $this->expectException(NotPermittedException::class); - $root = new \OC\Files\Node\Root( + $root = new Root( $this->manager, $this->view, $this->user, @@ -234,7 +240,7 @@ class FileTest extends NodeTest { $this->eventDispatcher, $this->cacheFactory, ); - $hook = function ($file) { + $hook = function ($file): void { throw new \Exception('Hooks are not supposed to be called'); }; @@ -243,15 +249,15 @@ class FileTest extends NodeTest { ->with('/bar/foo') ->willReturn($this->getFileInfo(['permissions' => 0])); - $node = new \OC\Files\Node\File($root, $this->view, '/bar/foo'); + $node = new File($root, $this->view, '/bar/foo'); $node->fopen('r'); } - public function testFOpenReadWriteNoReadPermissions() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testFOpenReadWriteNoReadPermissions(): void { + $this->expectException(NotPermittedException::class); - $root = new \OC\Files\Node\Root( + $root = new Root( $this->manager, $this->view, $this->user, @@ -261,24 +267,24 @@ class FileTest extends NodeTest { $this->eventDispatcher, $this->cacheFactory, ); - $hook = function () { + $hook = function (): void { throw new \Exception('Hooks are not supposed to be called'); }; $this->view->expects($this->once()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_UPDATE])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_UPDATE])); - $node = new \OC\Files\Node\File($root, $this->view, '/bar/foo'); + $node = new File($root, $this->view, '/bar/foo'); $node->fopen('w'); } - public function testFOpenReadWriteNoWritePermissions() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testFOpenReadWriteNoWritePermissions(): void { + $this->expectException(NotPermittedException::class); - $root = new \OC\Files\Node\Root( + $root = new Root( $this->manager, $this->view, $this->user, @@ -288,16 +294,16 @@ class FileTest extends NodeTest { $this->eventDispatcher, $this->cacheFactory, ); - $hook = function () { + $hook = function (): void { throw new \Exception('Hooks are not supposed to be called'); }; $this->view->expects($this->once()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_READ])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_READ])); - $node = new \OC\Files\Node\File($root, $this->view, '/bar/foo'); + $node = new File($root, $this->view, '/bar/foo'); $node->fopen('w'); } } diff --git a/tests/lib/Files/Node/FolderTest.php b/tests/lib/Files/Node/FolderTest.php index 546c9f84a1a..439535cf2c1 100644 --- a/tests/lib/Files/Node/FolderTest.php +++ b/tests/lib/Files/Node/FolderTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -17,18 +18,26 @@ use OC\Files\Node\File; use OC\Files\Node\Folder; use OC\Files\Node\Node; use OC\Files\Node\Root; +use OC\Files\Search\SearchBinaryOperator; use OC\Files\Search\SearchComparison; use OC\Files\Search\SearchOrder; use OC\Files\Search\SearchQuery; +use OC\Files\Storage\Storage; use OC\Files\Storage\Temporary; use OC\Files\Storage\Wrapper\Jail; +use OC\Files\View; +use OCP\Constants; use OCP\Files\Cache\ICacheEntry; +use OCP\Files\InvalidPathException; use OCP\Files\IRootFolder; use OCP\Files\Mount\IMountPoint; use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; +use OCP\Files\Search\ISearchBinaryOperator; use OCP\Files\Search\ISearchComparison; use OCP\Files\Search\ISearchOrder; -use OCP\Files\Storage; +use OCP\Files\Storage\IStorage; +use PHPUnit\Framework\MockObject\MockObject; /** * Class FolderTest @@ -37,7 +46,7 @@ use OCP\Files\Storage; * * @package Test\Files\Node */ -class FolderTest extends NodeTest { +class FolderTest extends NodeTestCase { protected function createTestNode($root, $view, $path, array $data = [], $internalPath = '', $storage = null) { $view->expects($this->any()) ->method('getRoot') @@ -61,10 +70,10 @@ class FolderTest extends NodeTest { return 'rmdir'; } - public function testGetDirectoryContent() { + public function testGetDirectoryContent(): void { $manager = $this->createMock(Manager::class); /** - * @var \OC\Files\View | \PHPUnit\Framework\MockObject\MockObject $view + * @var View|\PHPUnit\Framework\MockObject\MockObject $view */ $root = $this->getMockBuilder(Root::class) ->setConstructorArgs([$manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) @@ -96,7 +105,7 @@ class FolderTest extends NodeTest { $this->assertEquals(3, $children[1]->getId()); } - public function testGet() { + public function testGet(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) @@ -115,7 +124,7 @@ class FolderTest extends NodeTest { self::assertEquals($node, $parentNode->get('asd')); } - public function testNodeExists() { + public function testNodeExists(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) @@ -135,7 +144,7 @@ class FolderTest extends NodeTest { $this->assertTrue($node->nodeExists('asd')); } - public function testNodeExistsNotExists() { + public function testNodeExistsNotExists(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) @@ -147,13 +156,13 @@ class FolderTest extends NodeTest { $root->method('get') ->with('/bar/foo/asd') - ->will($this->throwException(new NotFoundException())); + ->willThrowException(new NotFoundException()); $node = new Folder($root, $view, '/bar/foo'); $this->assertFalse($node->nodeExists('asd')); } - public function testNewFolder() { + public function testNewFolder(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) @@ -165,7 +174,7 @@ class FolderTest extends NodeTest { $view->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL])); $view->method('mkdir') ->with('/bar/foo/asd') @@ -177,7 +186,7 @@ class FolderTest extends NodeTest { $this->assertEquals($child, $result); } - public function testNewFolderDeepParent() { + public function testNewFolderDeepParent(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) @@ -189,7 +198,7 @@ class FolderTest extends NodeTest { $view->method('getFileInfo') ->with('/foobar') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL])); $view->method('mkdir') ->with('/foobar/asd/sdf') @@ -202,8 +211,8 @@ class FolderTest extends NodeTest { } - public function testNewFolderNotPermitted() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testNewFolderNotPermitted(): void { + $this->expectException(NotPermittedException::class); $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); @@ -215,13 +224,13 @@ class FolderTest extends NodeTest { $view->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_READ])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_READ])); $node = new Folder($root, $view, '/bar/foo'); $node->newFolder('asd'); } - public function testNewFile() { + public function testNewFile(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) @@ -233,21 +242,21 @@ class FolderTest extends NodeTest { $view->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL])); $view->method('touch') ->with('/bar/foo/asd') ->willReturn(true); $node = new Folder($root, $view, '/bar/foo'); - $child = new \OC\Files\Node\File($root, $view, '/bar/foo/asd', null, $node); + $child = new File($root, $view, '/bar/foo/asd', null, $node); $result = $node->newFile('asd'); $this->assertEquals($child, $result); } - public function testNewFileNotPermitted() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testNewFileNotPermitted(): void { + $this->expectException(NotPermittedException::class); $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); @@ -259,13 +268,13 @@ class FolderTest extends NodeTest { $view->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_READ])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_READ])); $node = new Folder($root, $view, '/bar/foo'); $node->newFile('asd'); } - public function testGetFreeSpace() { + public function testGetFreeSpace(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) @@ -282,7 +291,7 @@ class FolderTest extends NodeTest { $this->assertEquals(100, $node->getFreeSpace()); } - public function testSearch() { + public function testSearch(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) @@ -290,20 +299,28 @@ class FolderTest extends NodeTest { ->getMock(); $root->method('getUser') ->willReturn($this->user); - /** @var Storage\IStorage $storage */ - $storage = $this->createMock(Storage\IStorage::class); + /** @var Storage\IStorage&MockObject $storage */ + $storage = $this->createMock(IStorage::class); $storage->method('getId')->willReturn('test::1'); $cache = new Cache($storage); $storage->method('getCache') ->willReturn($cache); + $storage->expects($this->atLeastOnce()) + ->method('getOwner') + ->with('qwerty') + ->willReturn(false); + $mount = $this->createMock(IMountPoint::class); - $mount->method('getStorage') + $mount->expects($this->atLeastOnce()) + ->method('getStorage') ->willReturn($storage); - $mount->method('getInternalPath') + $mount->expects($this->atLeastOnce()) + ->method('getInternalPath') ->willReturn('foo'); + $cache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $cache->insert('foo', ['size' => 200, 'mtime' => 55, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $cache->insert('foo/qwerty', ['size' => 200, 'mtime' => 55, 'mimetype' => 'text/plain']); @@ -322,18 +339,18 @@ class FolderTest extends NodeTest { $this->assertEquals('/bar/foo/qwerty', $result[0]->getPath()); } - public function testSearchInRoot() { + public function testSearchInRoot(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setMethods(['getUser', 'getMountsIn', 'getMount']) + ->onlyMethods(['getUser', 'getMountsIn', 'getMount']) ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); $root->expects($this->any()) ->method('getUser') ->willReturn($this->user); /** @var \PHPUnit\Framework\MockObject\MockObject|Storage $storage */ - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $storage->method('getId')->willReturn('test::2'); $cache = new Cache($storage); @@ -345,7 +362,10 @@ class FolderTest extends NodeTest { $storage->method('getCache') ->willReturn($cache); + $storage->method('getOwner') + ->willReturn('owner'); + $cache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $cache->insert('files', ['size' => 200, 'mtime' => 55, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $cache->insert('files/foo', ['size' => 200, 'mtime' => 55, 'mimetype' => 'text/plain']); @@ -363,7 +383,7 @@ class FolderTest extends NodeTest { $this->assertEquals('/foo', $result[0]->getPath()); } - public function testSearchInStorageRoot() { + public function testSearchInStorageRoot(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) @@ -371,7 +391,7 @@ class FolderTest extends NodeTest { ->getMock(); $root->method('getUser') ->willReturn($this->user); - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $storage->method('getId')->willReturn('test::1'); $cache = new Cache($storage); @@ -383,7 +403,10 @@ class FolderTest extends NodeTest { $storage->method('getCache') ->willReturn($cache); + $storage->method('getOwner') + ->willReturn('owner'); + $cache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $cache->insert('foo', ['size' => 200, 'mtime' => 55, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $cache->insert('foo/qwerty', ['size' => 200, 'mtime' => 55, 'mimetype' => 'text/plain']); @@ -403,7 +426,7 @@ class FolderTest extends NodeTest { $this->assertEquals('/bar/foo/qwerty', $result[0]->getPath()); } - public function testSearchSubStorages() { + public function testSearchSubStorages(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) @@ -412,10 +435,10 @@ class FolderTest extends NodeTest { $root->expects($this->any()) ->method('getUser') ->willReturn($this->user); - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $storage->method('getId')->willReturn('test::1'); $cache = new Cache($storage); - $subStorage = $this->createMock(Storage::class); + $subStorage = $this->createMock(IStorage::class); $subStorage->method('getId')->willReturn('test::2'); $subCache = new Cache($subStorage); $subMount = $this->getMockBuilder(MountPoint::class)->setConstructorArgs([Temporary::class, ''])->getMock(); @@ -434,13 +457,19 @@ class FolderTest extends NodeTest { $storage->method('getCache') ->willReturn($cache); + $storage->method('getOwner') + ->willReturn('owner'); $subStorage->method('getCache') ->willReturn($subCache); + $subStorage->method('getOwner') + ->willReturn('owner'); + $cache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $cache->insert('foo', ['size' => 200, 'mtime' => 55, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $cache->insert('foo/qwerty', ['size' => 200, 'mtime' => 55, 'mimetype' => 'text/plain']); + $subCache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $subCache->insert('asd', ['size' => 200, 'mtime' => 55, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $subCache->insert('asd/qwerty', ['size' => 200, 'mtime' => 55, 'mimetype' => 'text/plain']); @@ -461,7 +490,7 @@ class FolderTest extends NodeTest { $this->assertEquals(2, count($result)); } - public function testIsSubNode() { + public function testIsSubNode(): void { $rootFolderMock = $this->createMock(IRootFolder::class); $file = new Node($rootFolderMock, $this->view, '/foo/bar'); $folder = new Folder($rootFolderMock, $this->view, '/foo'); @@ -472,14 +501,14 @@ class FolderTest extends NodeTest { $this->assertFalse($folder->isSubNode($file)); } - public function testGetById() { + public function testGetById(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setMethods(['getMountsIn', 'getMount']) + ->onlyMethods(['getMountsIn', 'getMount']) ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); - $storage = $this->createMock(\OC\Files\Storage\Storage::class); + $storage = $this->createMock(Storage::class); $mount = new MountPoint($storage, '/bar'); $storage->method('getId')->willReturn(''); $cache = $this->getMockBuilder(Cache::class)->setConstructorArgs([$storage])->getMock(); @@ -488,6 +517,8 @@ class FolderTest extends NodeTest { $storage->method('getCache') ->willReturn($cache); + $storage->method('getOwner') + ->willReturn('owner'); $this->userMountCache->expects($this->any()) ->method('getMountsForFileId') @@ -519,14 +550,14 @@ class FolderTest extends NodeTest { $this->assertEquals('/bar/foo/qwerty', $result[0]->getPath()); } - public function testGetByIdMountRoot() { + public function testGetByIdMountRoot(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setMethods(['getMountsIn', 'getMount']) + ->onlyMethods(['getMountsIn', 'getMount']) ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); - $storage = $this->createMock(\OC\Files\Storage\Storage::class); + $storage = $this->createMock(Storage::class); $mount = new MountPoint($storage, '/bar'); $storage->method('getId')->willReturn(''); $cache = $this->getMockBuilder(Cache::class)->setConstructorArgs([$storage])->getMock(); @@ -535,6 +566,8 @@ class FolderTest extends NodeTest { $storage->method('getCache') ->willReturn($cache); + $storage->method('getOwner') + ->willReturn('owner'); $this->userMountCache->expects($this->any()) ->method('getMountsForFileId') @@ -562,14 +595,14 @@ class FolderTest extends NodeTest { $this->assertEquals('/bar', $result[0]->getPath()); } - public function testGetByIdOutsideFolder() { + public function testGetByIdOutsideFolder(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setMethods(['getMountsIn', 'getMount']) + ->onlyMethods(['getMountsIn', 'getMount']) ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); - $storage = $this->createMock(\OC\Files\Storage\Storage::class); + $storage = $this->createMock(Storage::class); $mount = new MountPoint($storage, '/bar'); $storage->method('getId')->willReturn(''); $cache = $this->getMockBuilder(Cache::class)->setConstructorArgs([$storage])->getMock(); @@ -578,6 +611,8 @@ class FolderTest extends NodeTest { $storage->method('getCache') ->willReturn($cache); + $storage->method('getOwner') + ->willReturn('owner'); $this->userMountCache->expects($this->any()) ->method('getMountsForFileId') @@ -604,14 +639,14 @@ class FolderTest extends NodeTest { $this->assertEquals(0, count($result)); } - public function testGetByIdMultipleStorages() { + public function testGetByIdMultipleStorages(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setMethods(['getMountsIn', 'getMount']) + ->onlyMethods(['getMountsIn', 'getMount']) ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); - $storage = $this->createMock(\OC\Files\Storage\Storage::class); + $storage = $this->createMock(Storage::class); $mount1 = new MountPoint($storage, '/bar'); $mount2 = new MountPoint($storage, '/bar/foo/asd'); $storage->method('getId')->willReturn(''); @@ -621,6 +656,8 @@ class FolderTest extends NodeTest { $storage->method('getCache') ->willReturn($cache); + $storage->method('getOwner') + ->willReturn('owner'); $this->userMountCache->method('getMountsForFileId') ->with(1) @@ -636,9 +673,6 @@ class FolderTest extends NodeTest { ), ]); - $storage->method('getCache') - ->willReturn($cache); - $cache->method('get') ->with(1) ->willReturn($fileInfo); @@ -653,7 +687,7 @@ class FolderTest extends NodeTest { $this->assertEquals('/bar/foo/asd/foo/qwerty', $result[1]->getPath()); } - public function uniqueNameProvider() { + public static function uniqueNameProvider(): array { return [ // input, existing, expected ['foo', [], 'foo'], @@ -662,15 +696,13 @@ class FolderTest extends NodeTest { ]; } - /** - * @dataProvider uniqueNameProvider - */ - public function testGetUniqueName($name, $existingFiles, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('uniqueNameProvider')] + public function testGetUniqueName($name, $existingFiles, $expected): void { $manager = $this->createMock(Manager::class); $folderPath = '/bar/foo'; $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setMethods(['getUser', 'getMountsIn', 'getMount']) + ->onlyMethods(['getUser', 'getMountsIn', 'getMount']) ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); @@ -695,10 +727,10 @@ class FolderTest extends NodeTest { $view = $this->getRootViewMock(); /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\Node\Root $root */ $root = $this->getMockBuilder(Root::class) - ->setMethods(['getUser', 'getMountsIn', 'getMount']) + ->onlyMethods(['getUser', 'getMountsIn', 'getMount']) ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); - /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\FileInfo $folderInfo */ + /** @var \PHPUnit\Framework\MockObject\MockObject|FileInfo $folderInfo */ $folderInfo = $this->getMockBuilder(FileInfo::class) ->disableOriginalConstructor()->getMock(); @@ -716,19 +748,23 @@ class FolderTest extends NodeTest { $cache = $storage->getCache(); + $cache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); + $cache->insert('bar', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); + $cache->insert('bar/foo', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); + $cache->insert('bar/asd', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $id1 = $cache->put('bar/foo/inside.txt', [ 'storage_mtime' => $baseTime, 'mtime' => $baseTime, 'mimetype' => 'text/plain', 'size' => 3, - 'permissions' => \OCP\Constants::PERMISSION_ALL, + 'permissions' => Constants::PERMISSION_ALL, ]); $id2 = $cache->put('bar/foo/old.txt', [ 'storage_mtime' => $baseTime - 100, 'mtime' => $baseTime - 100, 'mimetype' => 'text/plain', 'size' => 3, - 'permissions' => \OCP\Constants::PERMISSION_READ, + 'permissions' => Constants::PERMISSION_READ, ]); $cache->put('bar/asd/outside.txt', [ 'storage_mtime' => $baseTime, @@ -741,7 +777,7 @@ class FolderTest extends NodeTest { 'mtime' => $baseTime - 600, 'mimetype' => 'text/plain', 'size' => 3, - 'permissions' => \OCP\Constants::PERMISSION_ALL, + 'permissions' => Constants::PERMISSION_ALL, ]); $node = new Folder($root, $view, $folderPath, $folderInfo); @@ -754,16 +790,16 @@ class FolderTest extends NodeTest { $this->assertEquals([$id1, $id2, $id3], $ids); } - public function testRecentFolder() { + public function testRecentFolder(): void { $manager = $this->createMock(Manager::class); $folderPath = '/bar/foo'; $view = $this->getRootViewMock(); /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\Node\Root $root */ $root = $this->getMockBuilder(Root::class) - ->setMethods(['getUser', 'getMountsIn', 'getMount']) + ->onlyMethods(['getUser', 'getMountsIn', 'getMount']) ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); - /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\FileInfo $folderInfo */ + /** @var \PHPUnit\Framework\MockObject\MockObject|FileInfo $folderInfo */ $folderInfo = $this->getMockBuilder(FileInfo::class) ->disableOriginalConstructor()->getMock(); @@ -782,6 +818,9 @@ class FolderTest extends NodeTest { $cache = $storage->getCache(); + $cache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); + $cache->insert('bar', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); + $cache->insert('bar/foo', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $id1 = $cache->put('bar/foo/folder', [ 'storage_mtime' => $baseTime, 'mtime' => $baseTime, @@ -795,7 +834,7 @@ class FolderTest extends NodeTest { 'mimetype' => 'text/plain', 'size' => 3, 'parent' => $id1, - 'permissions' => \OCP\Constants::PERMISSION_ALL, + 'permissions' => Constants::PERMISSION_ALL, ]); $id3 = $cache->put('bar/foo/folder/asd.txt', [ 'storage_mtime' => $baseTime - 100, @@ -803,7 +842,7 @@ class FolderTest extends NodeTest { 'mimetype' => 'text/plain', 'size' => 3, 'parent' => $id1, - 'permissions' => \OCP\Constants::PERMISSION_ALL, + 'permissions' => Constants::PERMISSION_ALL, ]); $node = new Folder($root, $view, $folderPath, $folderInfo); @@ -818,16 +857,16 @@ class FolderTest extends NodeTest { $this->assertEquals($baseTime - 100, $nodes[1]->getMTime()); } - public function testRecentJail() { + public function testRecentJail(): void { $manager = $this->createMock(Manager::class); $folderPath = '/bar/foo'; $view = $this->getRootViewMock(); /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\Node\Root $root */ $root = $this->getMockBuilder(Root::class) - ->setMethods(['getUser', 'getMountsIn', 'getMount']) + ->onlyMethods(['getUser', 'getMountsIn', 'getMount']) ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); - /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\FileInfo $folderInfo */ + /** @var \PHPUnit\Framework\MockObject\MockObject|FileInfo $folderInfo */ $folderInfo = $this->getMockBuilder(FileInfo::class) ->disableOriginalConstructor()->getMock(); @@ -849,13 +888,16 @@ class FolderTest extends NodeTest { $cache = $storage->getCache(); + $cache->insert('', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); + $cache->insert('folder', ['size' => 0, 'mtime' => 0, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $id1 = $cache->put('folder/inside.txt', [ 'storage_mtime' => $baseTime, 'mtime' => $baseTime, 'mimetype' => 'text/plain', 'size' => 3, - 'permissions' => \OCP\Constants::PERMISSION_ALL, + 'permissions' => Constants::PERMISSION_ALL, ]); + $cache->put('outside.txt', [ 'storage_mtime' => $baseTime - 100, 'mtime' => $baseTime - 100, @@ -872,7 +914,7 @@ class FolderTest extends NodeTest { $this->assertEquals([$id1], $ids); } - public function offsetLimitProvider() { + public static function offsetLimitProvider(): array { return [ [0, 10, ['/bar/foo/foo1', '/bar/foo/foo2', '/bar/foo/foo3', '/bar/foo/foo4', '/bar/foo/sub1/foo5', '/bar/foo/sub1/foo6', '/bar/foo/sub2/foo7', '/bar/foo/sub2/foo8'], []], [0, 5, ['/bar/foo/foo1', '/bar/foo/foo2', '/bar/foo/foo3', '/bar/foo/foo4', '/bar/foo/sub1/foo5'], []], @@ -893,15 +935,15 @@ class FolderTest extends NodeTest { } /** - * @dataProvider offsetLimitProvider * @param int $offset * @param int $limit * @param string[] $expectedPaths * @param ISearchOrder[] $ordering * @throws NotFoundException - * @throws \OCP\Files\InvalidPathException + * @throws InvalidPathException */ - public function testSearchSubStoragesLimitOffset(int $offset, int $limit, array $expectedPaths, array $ordering) { + #[\PHPUnit\Framework\Attributes\DataProvider('offsetLimitProvider')] + public function testSearchSubStoragesLimitOffset(int $offset, int $limit, array $expectedPaths, array $ordering): void { if (!$ordering) { $ordering = [new SearchOrder(ISearchOrder::DIRECTION_ASCENDING, 'fileid')]; } @@ -914,14 +956,14 @@ class FolderTest extends NodeTest { $root->expects($this->any()) ->method('getUser') ->willReturn($this->user); - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $storage->method('getId')->willReturn('test::1'); $cache = new Cache($storage); - $subStorage1 = $this->createMock(Storage::class); + $subStorage1 = $this->createMock(IStorage::class); $subStorage1->method('getId')->willReturn('test::2'); $subCache1 = new Cache($subStorage1); $subMount1 = $this->getMockBuilder(MountPoint::class)->setConstructorArgs([Temporary::class, ''])->getMock(); - $subStorage2 = $this->createMock(Storage::class); + $subStorage2 = $this->createMock(IStorage::class); $subStorage2->method('getId')->willReturn('test::3'); $subCache2 = new Cache($subStorage2); $subMount2 = $this->getMockBuilder(MountPoint::class)->setConstructorArgs([Temporary::class, ''])->getMock(); @@ -940,9 +982,13 @@ class FolderTest extends NodeTest { $storage->method('getCache') ->willReturn($cache); + $storage->method('getOwner') + ->willReturn('owner'); $subStorage1->method('getCache') ->willReturn($subCache1); + $subStorage1->method('getOwner') + ->willReturn('owner'); $subMount2->method('getStorage') ->willReturn($subStorage2); @@ -952,15 +998,22 @@ class FolderTest extends NodeTest { $subStorage2->method('getCache') ->willReturn($subCache2); + $subStorage2->method('getOwner') + ->willReturn('owner'); + + $cache->insert('', ['size' => 0, 'mtime' => 10, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); + $cache->insert('foo', ['size' => 0, 'mtime' => 10, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $cache->insert('foo/foo1', ['size' => 200, 'mtime' => 10, 'mimetype' => 'text/plain']); $cache->insert('foo/foo2', ['size' => 200, 'mtime' => 20, 'mimetype' => 'text/plain']); $cache->insert('foo/foo3', ['size' => 200, 'mtime' => 30, 'mimetype' => 'text/plain']); $cache->insert('foo/foo4', ['size' => 200, 'mtime' => 40, 'mimetype' => 'text/plain']); + $subCache1->insert('', ['size' => 0, 'mtime' => 10, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $subCache1->insert('foo5', ['size' => 300, 'mtime' => 15, 'mimetype' => 'text/plain']); $subCache1->insert('foo6', ['size' => 300, 'mtime' => 50, 'mimetype' => 'text/plain']); + $subCache2->insert('', ['size' => 0, 'mtime' => 10, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]); $subCache2->insert('foo7', ['size' => 200, 'mtime' => 5, 'mimetype' => 'text/plain']); $subCache2->insert('foo8', ['size' => 200, 'mtime' => 60, 'mimetype' => 'text/plain']); @@ -974,7 +1027,11 @@ class FolderTest extends NodeTest { $node = new Folder($root, $view, '/bar/foo'); $comparison = new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%foo%'); - $query = new SearchQuery($comparison, $limit, $offset, $ordering); + $operator = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ + $comparison, + new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_NOT, [new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', ICacheEntry::DIRECTORY_MIMETYPE)]), + ]); + $query = new SearchQuery($operator, $limit, $offset, $ordering); $result = $node->search($query); $cache->clear(); $subCache1->clear(); diff --git a/tests/lib/Files/Node/HookConnectorTest.php b/tests/lib/Files/Node/HookConnectorTest.php index 7cc2da516bb..3f3957bab1d 100644 --- a/tests/lib/Files/Node/HookConnectorTest.php +++ b/tests/lib/Files/Node/HookConnectorTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -15,6 +16,7 @@ use OC\Files\View; use OC\Memcache\ArrayCache; use OCP\EventDispatcher\GenericEvent as APIGenericEvent; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Config\IUserMountCache; use OCP\Files\Events\Node\AbstractNodeEvent; use OCP\Files\Events\Node\AbstractNodesEvent; use OCP\Files\Events\Node\BeforeNodeCopiedEvent; @@ -32,6 +34,7 @@ use OCP\Files\Events\Node\NodeWrittenEvent; use OCP\Files\Node; use OCP\ICacheFactory; use OCP\IUserManager; +use OCP\Server; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\GenericEvent; use Test\TestCase; @@ -49,7 +52,7 @@ class HookConnectorTest extends TestCase { use UserTrait; use MountProviderTrait; - /** @var IEventDispatcher */ + /** @var IEventDispatcher */ protected $eventDispatcher; private LoggerInterface $logger; @@ -79,15 +82,15 @@ class HookConnectorTest extends TestCase { $this->root = new Root( Filesystem::getMountManager(), $this->view, - \OC::$server->getUserManager()->get($this->userId), - \OC::$server->getUserMountCache(), + Server::get(IUserManager::class)->get($this->userId), + Server::get(IUserMountCache::class), $this->createMock(LoggerInterface::class), $this->createMock(IUserManager::class), $this->createMock(IEventDispatcher::class), $cacheFactory, ); - $this->eventDispatcher = \OC::$server->query(IEventDispatcher::class); - $this->logger = \OC::$server->query(LoggerInterface::class); + $this->eventDispatcher = Server::get(IEventDispatcher::class); + $this->logger = Server::get(LoggerInterface::class); } protected function tearDown(): void { @@ -96,51 +99,51 @@ class HookConnectorTest extends TestCase { \OC_Util::tearDownFS(); } - public function viewToNodeProvider() { + public static function viewToNodeProvider(): array { return [ - [function () { + [function (): void { Filesystem::file_put_contents('test.txt', 'asd'); }, 'preWrite', '\OCP\Files::preWrite', BeforeNodeWrittenEvent::class], - [function () { + [function (): void { Filesystem::file_put_contents('test.txt', 'asd'); }, 'postWrite', '\OCP\Files::postWrite', NodeWrittenEvent::class], - [function () { + [function (): void { Filesystem::file_put_contents('test.txt', 'asd'); }, 'preCreate', '\OCP\Files::preCreate', BeforeNodeCreatedEvent::class], - [function () { + [function (): void { Filesystem::file_put_contents('test.txt', 'asd'); }, 'postCreate', '\OCP\Files::postCreate', NodeCreatedEvent::class], - [function () { + [function (): void { Filesystem::mkdir('test.txt'); }, 'preCreate', '\OCP\Files::preCreate', BeforeNodeCreatedEvent::class], - [function () { + [function (): void { Filesystem::mkdir('test.txt'); }, 'postCreate', '\OCP\Files::postCreate', NodeCreatedEvent::class], - [function () { + [function (): void { Filesystem::touch('test.txt'); }, 'preTouch', '\OCP\Files::preTouch', BeforeNodeTouchedEvent::class], - [function () { + [function (): void { Filesystem::touch('test.txt'); }, 'postTouch', '\OCP\Files::postTouch', NodeTouchedEvent::class], - [function () { + [function (): void { Filesystem::touch('test.txt'); }, 'preCreate', '\OCP\Files::preCreate', BeforeNodeCreatedEvent::class], - [function () { + [function (): void { Filesystem::touch('test.txt'); }, 'postCreate', '\OCP\Files::postCreate', NodeCreatedEvent::class], - [function () { + [function (): void { Filesystem::file_put_contents('test.txt', 'asd'); Filesystem::unlink('test.txt'); }, 'preDelete', '\OCP\Files::preDelete', BeforeNodeDeletedEvent::class], - [function () { + [function (): void { Filesystem::file_put_contents('test.txt', 'asd'); Filesystem::unlink('test.txt'); }, 'postDelete', '\OCP\Files::postDelete', NodeDeletedEvent::class], - [function () { + [function (): void { Filesystem::mkdir('test.txt'); Filesystem::rmdir('test.txt'); }, 'preDelete', '\OCP\Files::preDelete', BeforeNodeDeletedEvent::class], - [function () { + [function (): void { Filesystem::mkdir('test.txt'); Filesystem::rmdir('test.txt'); }, 'postDelete', '\OCP\Files::postDelete', NodeDeletedEvent::class], @@ -150,16 +153,16 @@ class HookConnectorTest extends TestCase { /** * @param callable $operation * @param string $expectedHook - * @dataProvider viewToNodeProvider */ - public function testViewToNode(callable $operation, $expectedHook, $expectedLegacyEvent, $expectedEvent) { + #[\PHPUnit\Framework\Attributes\DataProvider('viewToNodeProvider')] + public function testViewToNode(callable $operation, $expectedHook, $expectedLegacyEvent, $expectedEvent): void { $connector = new HookConnector($this->root, $this->view, $this->eventDispatcher, $this->logger); $connector->viewToNode(); $hookCalled = false; /** @var Node $hookNode */ $hookNode = null; - $this->root->listen('\OC\Files', $expectedHook, function ($node) use (&$hookNode, &$hookCalled) { + $this->root->listen('\OC\Files', $expectedHook, function ($node) use (&$hookNode, &$hookCalled): void { $hookCalled = true; $hookNode = $node; }); @@ -167,7 +170,7 @@ class HookConnectorTest extends TestCase { $dispatcherCalled = false; /** @var Node $dispatcherNode */ $dispatcherNode = null; - $this->eventDispatcher->addListener($expectedLegacyEvent, function ($event) use (&$dispatcherCalled, &$dispatcherNode) { + $this->eventDispatcher->addListener($expectedLegacyEvent, function ($event) use (&$dispatcherCalled, &$dispatcherNode): void { /** @var GenericEvent|APIGenericEvent $event */ $dispatcherCalled = true; $dispatcherNode = $event->getSubject(); @@ -175,7 +178,7 @@ class HookConnectorTest extends TestCase { $newDispatcherCalled = false; $newDispatcherNode = null; - $this->eventDispatcher->addListener($expectedEvent, function ($event) use ($expectedEvent, &$newDispatcherCalled, &$newDispatcherNode) { + $this->eventDispatcher->addListener($expectedEvent, function ($event) use ($expectedEvent, &$newDispatcherCalled, &$newDispatcherNode): void { if ($event instanceof $expectedEvent) { /** @var AbstractNodeEvent $event */ $newDispatcherCalled = true; @@ -195,21 +198,21 @@ class HookConnectorTest extends TestCase { $this->assertEquals('/' . $this->userId . '/files/test.txt', $newDispatcherNode->getPath()); } - public function viewToNodeProviderCopyRename() { + public static function viewToNodeProviderCopyRename(): array { return [ - [function () { + [function (): void { Filesystem::file_put_contents('source', 'asd'); Filesystem::rename('source', 'target'); }, 'preRename', '\OCP\Files::preRename', BeforeNodeRenamedEvent::class], - [function () { + [function (): void { Filesystem::file_put_contents('source', 'asd'); Filesystem::rename('source', 'target'); }, 'postRename', '\OCP\Files::postRename', NodeRenamedEvent::class], - [function () { + [function (): void { Filesystem::file_put_contents('source', 'asd'); Filesystem::copy('source', 'target'); }, 'preCopy', '\OCP\Files::preCopy', BeforeNodeCopiedEvent::class], - [function () { + [function (): void { Filesystem::file_put_contents('source', 'asd'); Filesystem::copy('source', 'target'); }, 'postCopy', '\OCP\Files::postCopy', NodeCopiedEvent::class], @@ -219,9 +222,9 @@ class HookConnectorTest extends TestCase { /** * @param callable $operation * @param string $expectedHook - * @dataProvider viewToNodeProviderCopyRename */ - public function testViewToNodeCopyRename(callable $operation, $expectedHook, $expectedLegacyEvent, $expectedEvent) { + #[\PHPUnit\Framework\Attributes\DataProvider('viewToNodeProviderCopyRename')] + public function testViewToNodeCopyRename(callable $operation, $expectedHook, $expectedLegacyEvent, $expectedEvent): void { $connector = new HookConnector($this->root, $this->view, $this->eventDispatcher, $this->logger); $connector->viewToNode(); $hookCalled = false; @@ -230,7 +233,7 @@ class HookConnectorTest extends TestCase { /** @var Node $hookTargetNode */ $hookTargetNode = null; - $this->root->listen('\OC\Files', $expectedHook, function ($sourceNode, $targetNode) use (&$hookCalled, &$hookSourceNode, &$hookTargetNode) { + $this->root->listen('\OC\Files', $expectedHook, function ($sourceNode, $targetNode) use (&$hookCalled, &$hookSourceNode, &$hookTargetNode): void { $hookCalled = true; $hookSourceNode = $sourceNode; $hookTargetNode = $targetNode; @@ -241,7 +244,7 @@ class HookConnectorTest extends TestCase { $dispatcherSourceNode = null; /** @var Node $dispatcherTargetNode */ $dispatcherTargetNode = null; - $this->eventDispatcher->addListener($expectedLegacyEvent, function ($event) use (&$dispatcherSourceNode, &$dispatcherTargetNode, &$dispatcherCalled) { + $this->eventDispatcher->addListener($expectedLegacyEvent, function ($event) use (&$dispatcherSourceNode, &$dispatcherTargetNode, &$dispatcherCalled): void { /** @var GenericEvent|APIGenericEvent $event */ $dispatcherCalled = true; [$dispatcherSourceNode, $dispatcherTargetNode] = $event->getSubject(); @@ -252,7 +255,7 @@ class HookConnectorTest extends TestCase { $newDispatcherSourceNode = null; /** @var Node $dispatcherTargetNode */ $newDispatcherTargetNode = null; - $this->eventDispatcher->addListener($expectedEvent, function ($event) use ($expectedEvent, &$newDispatcherSourceNode, &$newDispatcherTargetNode, &$newDispatcherCalled) { + $this->eventDispatcher->addListener($expectedEvent, function ($event) use ($expectedEvent, &$newDispatcherSourceNode, &$newDispatcherTargetNode, &$newDispatcherCalled): void { if ($event instanceof $expectedEvent) { /** @var AbstractNodesEvent$event */ $newDispatcherCalled = true; @@ -276,14 +279,14 @@ class HookConnectorTest extends TestCase { $this->assertEquals('/' . $this->userId . '/files/target', $newDispatcherTargetNode->getPath()); } - public function testPostDeleteMeta() { + public function testPostDeleteMeta(): void { $connector = new HookConnector($this->root, $this->view, $this->eventDispatcher, $this->logger); $connector->viewToNode(); $hookCalled = false; /** @var Node $hookNode */ $hookNode = null; - $this->root->listen('\OC\Files', 'postDelete', function ($node) use (&$hookNode, &$hookCalled) { + $this->root->listen('\OC\Files', 'postDelete', function ($node) use (&$hookNode, &$hookCalled): void { $hookCalled = true; $hookNode = $node; }); @@ -291,7 +294,7 @@ class HookConnectorTest extends TestCase { $dispatcherCalled = false; /** @var Node $dispatcherNode */ $dispatcherNode = null; - $this->eventDispatcher->addListener('\OCP\Files::postDelete', function ($event) use (&$dispatcherCalled, &$dispatcherNode) { + $this->eventDispatcher->addListener('\OCP\Files::postDelete', function ($event) use (&$dispatcherCalled, &$dispatcherNode): void { /** @var GenericEvent|APIGenericEvent $event */ $dispatcherCalled = true; $dispatcherNode = $event->getSubject(); @@ -300,7 +303,7 @@ class HookConnectorTest extends TestCase { $newDispatcherCalled = false; /** @var Node $dispatcherNode */ $newDispatcherNode = null; - $this->eventDispatcher->addListener(NodeDeletedEvent::class, function ($event) use (&$newDispatcherCalled, &$newDispatcherNode) { + $this->eventDispatcher->addListener(NodeDeletedEvent::class, function ($event) use (&$newDispatcherCalled, &$newDispatcherNode): void { if ($event instanceof NodeDeletedEvent) { /** @var AbstractNodeEvent $event */ $newDispatcherCalled = true; diff --git a/tests/lib/Files/Node/IntegrationTest.php b/tests/lib/Files/Node/IntegrationTest.php index 7d87cdb5dd0..f059afa1625 100644 --- a/tests/lib/Files/Node/IntegrationTest.php +++ b/tests/lib/Files/Node/IntegrationTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -8,13 +9,16 @@ namespace Test\Files\Node; use OC\Files\Node\Root; +use OC\Files\Storage\Storage; use OC\Files\Storage\Temporary; use OC\Files\View; use OC\Memcache\ArrayCache; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Config\IUserMountCache; use OCP\Files\Mount\IMountManager; use OCP\ICacheFactory; use OCP\IUserManager; +use OCP\Server; use Psr\Log\LoggerInterface; use Test\Traits\UserTrait; @@ -34,20 +38,19 @@ class IntegrationTest extends \Test\TestCase { private $root; /** - * @var \OC\Files\Storage\Storage[] + * @var Storage[] */ private $storages; /** - * @var \OC\Files\View $view + * @var View $view */ private $view; protected function setUp(): void { parent::setUp(); - /** @var IMountManager $manager */ - $manager = \OC::$server->get(IMountManager::class); + $manager = Server::get(IMountManager::class); \OC_Hook::clear('OC_Filesystem'); @@ -64,7 +67,7 @@ class IntegrationTest extends \Test\TestCase { $manager, $this->view, $user, - \OC::$server->getUserMountCache(), + Server::get(IUserMountCache::class), $this->createMock(LoggerInterface::class), $this->createMock(IUserManager::class), $this->createMock(IEventDispatcher::class), @@ -88,7 +91,7 @@ class IntegrationTest extends \Test\TestCase { parent::tearDown(); } - public function testBasicFile() { + public function testBasicFile(): void { $file = $this->root->newFile('/foo.txt'); $this->assertCount(2, $this->root->getDirectoryListing()); $this->assertTrue($this->root->nodeExists('/foo.txt')); @@ -111,7 +114,7 @@ class IntegrationTest extends \Test\TestCase { $this->assertEquals('qwerty', $file->getContent()); } - public function testBasicFolder() { + public function testBasicFolder(): void { $folder = $this->root->newFolder('/foo'); $this->assertTrue($this->root->nodeExists('/foo')); $file = $folder->newFile('/bar'); diff --git a/tests/lib/Files/Node/NodeTest.php b/tests/lib/Files/Node/NodeTestCase.php index b00d9e1b4de..4aecd0fef11 100644 --- a/tests/lib/Files/Node/NodeTest.php +++ b/tests/lib/Files/Node/NodeTestCase.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -9,14 +10,23 @@ namespace Test\Files\Node; use OC\Files\FileInfo; use OC\Files\Mount\Manager; +use OC\Files\Node\File; +use OC\Files\Node\Folder; +use OC\Files\Node\Root; +use OC\Files\Storage\Storage; use OC\Files\View; use OC\Memcache\ArrayCache; +use OC\User\User; +use OCP\Constants; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Config\IUserMountCache; +use OCP\Files\InvalidPathException; use OCP\Files\IRootFolder; use OCP\Files\Mount\IMountPoint; use OCP\Files\Node; use OCP\Files\NotFoundException; -use OCP\Files\Storage; +use OCP\Files\NotPermittedException; +use OCP\Files\Storage\IStorage; use OCP\ICacheFactory; use OCP\IUser; use OCP\IUserManager; @@ -27,16 +37,16 @@ use Psr\Log\LoggerInterface; * * @package Test\Files\Node */ -abstract class NodeTest extends \Test\TestCase { - /** @var \OC\User\User */ +abstract class NodeTestCase extends \Test\TestCase { + /** @var User */ protected $user; /** @var \OC\Files\Mount\Manager */ protected $manager; - /** @var \OC\Files\View|\PHPUnit\Framework\MockObject\MockObject */ + /** @var View|\PHPUnit\Framework\MockObject\MockObject */ protected $view; /** @var \OC\Files\Node\Root|\PHPUnit\Framework\MockObject\MockObject */ protected $root; - /** @var \OCP\Files\Config\IUserMountCache|\PHPUnit\Framework\MockObject\MockObject */ + /** @var IUserMountCache|\PHPUnit\Framework\MockObject\MockObject */ protected $userMountCache; /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $logger; @@ -71,13 +81,13 @@ abstract class NodeTest extends \Test\TestCase { ->willReturnCallback(function () { return new ArrayCache(); }); - $this->root = $this->getMockBuilder('\OC\Files\Node\Root') + $this->root = $this->getMockBuilder(Root::class) ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) ->getMock(); } /** - * @return \OC\Files\View | \PHPUnit\Framework\MockObject\MockObject $view + * @return View|\PHPUnit\Framework\MockObject\MockObject $view */ protected function getRootViewMock() { $view = $this->createMock(View::class); @@ -111,7 +121,7 @@ abstract class NodeTest extends \Test\TestCase { abstract protected function getViewDeleteMethod(); protected function getMockStorage() { - $storage = $this->getMockBuilder(Storage::class) + $storage = $this->getMockBuilder(IStorage::class) ->disableOriginalConstructor() ->getMock(); $storage->expects($this->any()) @@ -127,7 +137,7 @@ abstract class NodeTest extends \Test\TestCase { return new FileInfo('', $this->getMockStorage(), $internalPath, $data, $mount); } - public function testDelete() { + public function testDelete(): void { $this->root->expects($this->exactly(2)) ->method('emit') ->willReturn(true); @@ -138,7 +148,7 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->once()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL])); $this->view->expects($this->once()) ->method($this->getViewDeleteMethod()) @@ -149,13 +159,13 @@ abstract class NodeTest extends \Test\TestCase { $node->delete(); } - public function testDeleteHooks() { + public function testDeleteHooks(): void { $test = $this; $hooksRun = 0; /** * @param \OC\Files\Node\File $node */ - $preListener = function ($node) use (&$test, &$hooksRun) { + $preListener = function ($node) use (&$test, &$hooksRun): void { $test->assertInstanceOf($this->getNodeClass(), $node); $test->assertEquals('foo', $node->getInternalPath()); $test->assertEquals('/bar/foo', $node->getPath()); @@ -166,7 +176,7 @@ abstract class NodeTest extends \Test\TestCase { /** * @param \OC\Files\Node\File $node */ - $postListener = function ($node) use (&$test, &$hooksRun) { + $postListener = function ($node) use (&$test, &$hooksRun): void { $test->assertInstanceOf($this->getNonExistingNodeClass(), $node); $test->assertEquals('foo', $node->getInternalPath()); $test->assertEquals('/bar/foo', $node->getPath()); @@ -175,7 +185,7 @@ abstract class NodeTest extends \Test\TestCase { $hooksRun++; }; - $root = new \OC\Files\Node\Root( + $root = new Root( $this->manager, $this->view, $this->user, @@ -192,7 +202,7 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->any()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL, 'fileid' => 1, 'mimetype' => 'text/plain'], 'foo')); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL, 'fileid' => 1, 'mimetype' => 'text/plain'], 'foo')); $this->view->expects($this->once()) ->method($this->getViewDeleteMethod()) @@ -205,8 +215,8 @@ abstract class NodeTest extends \Test\TestCase { } - public function testDeleteNotPermitted() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testDeleteNotPermitted(): void { + $this->expectException(NotPermittedException::class); $this->root->expects($this->any()) ->method('getUser') @@ -215,14 +225,14 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->once()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_READ])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_READ])); $node = $this->createTestNode($this->root, $this->view, '/bar/foo'); $node->delete(); } - public function testStat() { + public function testStat(): void { $this->root->expects($this->any()) ->method('getUser') ->willReturn($this->user); @@ -244,7 +254,7 @@ abstract class NodeTest extends \Test\TestCase { $this->assertEquals($stat, $node->stat()); } - public function testGetId() { + public function testGetId(): void { $this->root->expects($this->any()) ->method('getUser') ->willReturn($this->user); @@ -265,7 +275,7 @@ abstract class NodeTest extends \Test\TestCase { $this->assertEquals(1, $node->getId()); } - public function testGetSize() { + public function testGetSize(): void { $this->root->expects($this->any()) ->method('getUser') ->willReturn($this->user); @@ -287,7 +297,7 @@ abstract class NodeTest extends \Test\TestCase { $this->assertEquals(100, $node->getSize()); } - public function testGetEtag() { + public function testGetEtag(): void { $this->root->expects($this->any()) ->method('getUser') ->willReturn($this->user); @@ -308,7 +318,7 @@ abstract class NodeTest extends \Test\TestCase { $this->assertEquals('qwerty', $node->getEtag()); } - public function testGetMTime() { + public function testGetMTime(): void { $this->root->expects($this->any()) ->method('getUser') ->willReturn($this->user); @@ -329,12 +339,12 @@ abstract class NodeTest extends \Test\TestCase { $this->assertEquals(50, $node->getMTime()); } - public function testGetStorage() { + public function testGetStorage(): void { $this->root->expects($this->any()) ->method('getUser') ->willReturn($this->user); /** - * @var \OC\Files\Storage\Storage | \PHPUnit\Framework\MockObject\MockObject $storage + * @var Storage|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->getMockBuilder('\OC\Files\Storage\Storage') ->disableOriginalConstructor() @@ -344,7 +354,7 @@ abstract class NodeTest extends \Test\TestCase { $this->assertEquals($storage, $node->getStorage()); } - public function testGetPath() { + public function testGetPath(): void { $this->root->expects($this->any()) ->method('getUser') ->willReturn($this->user); @@ -353,12 +363,12 @@ abstract class NodeTest extends \Test\TestCase { $this->assertEquals('/bar/foo', $node->getPath()); } - public function testGetInternalPath() { + public function testGetInternalPath(): void { $this->root->expects($this->any()) ->method('getUser') ->willReturn($this->user); /** - * @var \OC\Files\Storage\Storage | \PHPUnit\Framework\MockObject\MockObject $storage + * @var Storage|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->getMockBuilder('\OC\Files\Storage\Storage') ->disableOriginalConstructor() @@ -374,7 +384,7 @@ abstract class NodeTest extends \Test\TestCase { $this->assertEquals('foo', $node->getInternalPath()); } - public function testGetName() { + public function testGetName(): void { $this->root->expects($this->any()) ->method('getUser') ->willReturn($this->user); @@ -383,7 +393,7 @@ abstract class NodeTest extends \Test\TestCase { $this->assertEquals('foo', $node->getName()); } - public function testTouchSetMTime() { + public function testTouchSetMTime(): void { $this->root->expects($this->any()) ->method('getUser') ->willReturn($this->user); @@ -396,20 +406,20 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->once()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL])); $node = $this->createTestNode($this->root, $this->view, '/bar/foo'); $node->touch(100); $this->assertEquals(100, $node->getMTime()); } - public function testTouchHooks() { + public function testTouchHooks(): void { $test = $this; $hooksRun = 0; /** * @param \OC\Files\Node\File $node */ - $preListener = function ($node) use (&$test, &$hooksRun) { + $preListener = function ($node) use (&$test, &$hooksRun): void { $test->assertEquals('foo', $node->getInternalPath()); $test->assertEquals('/bar/foo', $node->getPath()); $hooksRun++; @@ -418,13 +428,13 @@ abstract class NodeTest extends \Test\TestCase { /** * @param \OC\Files\Node\File $node */ - $postListener = function ($node) use (&$test, &$hooksRun) { + $postListener = function ($node) use (&$test, &$hooksRun): void { $test->assertEquals('foo', $node->getInternalPath()); $test->assertEquals('/bar/foo', $node->getPath()); $hooksRun++; }; - $root = new \OC\Files\Node\Root( + $root = new Root( $this->manager, $this->view, $this->user, @@ -445,7 +455,7 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->any()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL], 'foo')); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL], 'foo')); $node = $this->createTestNode($root, $this->view, '/bar/foo'); $node->touch(100); @@ -453,8 +463,8 @@ abstract class NodeTest extends \Test\TestCase { } - public function testTouchNotPermitted() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testTouchNotPermitted(): void { + $this->expectException(NotPermittedException::class); $this->root->expects($this->any()) ->method('getUser') @@ -463,21 +473,21 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->any()) ->method('getFileInfo') ->with('/bar/foo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_READ])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_READ])); $node = $this->createTestNode($this->root, $this->view, '/bar/foo'); $node->touch(100); } - public function testInvalidPath() { - $this->expectException(\OCP\Files\InvalidPathException::class); + public function testInvalidPath(): void { + $this->expectException(InvalidPathException::class); $node = $this->createTestNode($this->root, $this->view, '/../foo'); $node->getFileInfo(); } - public function testCopySameStorage() { + public function testCopySameStorage(): void { $this->view->expects($this->any()) ->method('copy') ->with('/bar/foo', '/bar/asd') @@ -485,10 +495,10 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->any()) ->method('getFileInfo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL, 'fileid' => 3])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL, 'fileid' => 3])); $node = $this->createTestNode($this->root, $this->view, '/bar/foo'); - $parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar'); + $parentNode = new Folder($this->root, $this->view, '/bar'); $newNode = $this->createTestNode($this->root, $this->view, '/bar/asd'); $this->root->method('get') @@ -503,11 +513,11 @@ abstract class NodeTest extends \Test\TestCase { } - public function testCopyNotPermitted() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testCopyNotPermitted(): void { + $this->expectException(NotPermittedException::class); /** - * @var \OC\Files\Storage\Storage | \PHPUnit\Framework\MockObject\MockObject $storage + * @var Storage|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->createMock('\OC\Files\Storage\Storage'); @@ -519,10 +529,10 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->any()) ->method('getFileInfo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_READ, 'fileid' => 3])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_READ, 'fileid' => 3])); $node = $this->createTestNode($this->root, $this->view, '/bar/foo'); - $parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar'); + $parentNode = new Folder($this->root, $this->view, '/bar'); $this->root->expects($this->once()) ->method('get') @@ -534,8 +544,8 @@ abstract class NodeTest extends \Test\TestCase { } - public function testCopyNoParent() { - $this->expectException(\OCP\Files\NotFoundException::class); + public function testCopyNoParent(): void { + $this->expectException(NotFoundException::class); $this->view->expects($this->never()) ->method('copy'); @@ -545,20 +555,20 @@ abstract class NodeTest extends \Test\TestCase { $this->root->expects($this->once()) ->method('get') ->with('/bar/asd') - ->will($this->throwException(new NotFoundException())); + ->willThrowException(new NotFoundException()); $node->copy('/bar/asd/foo'); } - public function testCopyParentIsFile() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testCopyParentIsFile(): void { + $this->expectException(NotPermittedException::class); $this->view->expects($this->never()) ->method('copy'); $node = $this->createTestNode($this->root, $this->view, '/bar/foo'); - $parentNode = new \OC\Files\Node\File($this->root, $this->view, '/bar'); + $parentNode = new File($this->root, $this->view, '/bar'); $this->root->expects($this->once()) ->method('get') @@ -569,7 +579,7 @@ abstract class NodeTest extends \Test\TestCase { $node->copy('/bar/asd'); } - public function testMoveSameStorage() { + public function testMoveSameStorage(): void { $this->view->expects($this->any()) ->method('rename') ->with('/bar/foo', '/bar/asd') @@ -577,10 +587,10 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->any()) ->method('getFileInfo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL, 'fileid' => 1])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL, 'fileid' => 1])); $node = $this->createTestNode($this->root, $this->view, '/bar/foo'); - $parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar'); + $parentNode = new Folder($this->root, $this->view, '/bar'); $this->root->expects($this->any()) ->method('get') @@ -592,7 +602,7 @@ abstract class NodeTest extends \Test\TestCase { $this->assertEquals('/bar/asd', $node->getPath()); } - public function moveOrCopyProvider() { + public static function moveOrCopyProvider(): array { return [ ['move', 'rename', 'preRename', 'postRename'], ['copy', 'copy', 'preCopy', 'postCopy'], @@ -600,17 +610,17 @@ abstract class NodeTest extends \Test\TestCase { } /** - * @dataProvider moveOrCopyProvider * @param string $operationMethod * @param string $viewMethod * @param string $preHookName * @param string $postHookName */ - public function testMoveCopyHooks($operationMethod, $viewMethod, $preHookName, $postHookName) { + #[\PHPUnit\Framework\Attributes\DataProvider('moveOrCopyProvider')] + public function testMoveCopyHooks($operationMethod, $viewMethod, $preHookName, $postHookName): void { /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject $root */ - $root = $this->getMockBuilder('\OC\Files\Node\Root') + $root = $this->getMockBuilder(Root::class) ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) - ->setMethods(['get']) + ->onlyMethods(['get']) ->getMock(); $this->view->expects($this->any()) @@ -620,13 +630,13 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->any()) ->method('getFileInfo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL, 'fileid' => 1])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL, 'fileid' => 1])); /** * @var \OC\Files\Node\File|\PHPUnit\Framework\MockObject\MockObject $node */ $node = $this->createTestNode($root, $this->view, '/bar/foo'); - $parentNode = new \OC\Files\Node\Folder($root, $this->view, '/bar'); + $parentNode = new Folder($root, $this->view, '/bar'); $targetTestNode = $this->createTestNode($root, $this->view, '/bar/asd'); $root->expects($this->any()) @@ -635,7 +645,7 @@ abstract class NodeTest extends \Test\TestCase { $hooksRun = 0; - $preListener = function (Node $sourceNode, Node $targetNode) use (&$hooksRun, $node) { + $preListener = function (Node $sourceNode, Node $targetNode) use (&$hooksRun, $node): void { $this->assertSame($node, $sourceNode); $this->assertInstanceOf($this->getNodeClass(), $sourceNode); $this->assertInstanceOf($this->getNonExistingNodeClass(), $targetNode); @@ -643,7 +653,7 @@ abstract class NodeTest extends \Test\TestCase { $hooksRun++; }; - $postListener = function (Node $sourceNode, Node $targetNode) use (&$hooksRun, $node, $targetTestNode) { + $postListener = function (Node $sourceNode, Node $targetNode) use (&$hooksRun, $node, $targetTestNode): void { $this->assertSame($node, $sourceNode); $this->assertNotSame($node, $targetNode); $this->assertSame($targetTestNode, $targetNode); @@ -652,13 +662,13 @@ abstract class NodeTest extends \Test\TestCase { $hooksRun++; }; - $preWriteListener = function (Node $targetNode) use (&$hooksRun) { + $preWriteListener = function (Node $targetNode) use (&$hooksRun): void { $this->assertInstanceOf($this->getNonExistingNodeClass(), $targetNode); $this->assertEquals('/bar/asd', $targetNode->getPath()); $hooksRun++; }; - $postWriteListener = function (Node $targetNode) use (&$hooksRun, $targetTestNode) { + $postWriteListener = function (Node $targetNode) use (&$hooksRun, $targetTestNode): void { $this->assertSame($targetTestNode, $targetNode); $hooksRun++; }; @@ -674,18 +684,18 @@ abstract class NodeTest extends \Test\TestCase { } - public function testMoveNotPermitted() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testMoveNotPermitted(): void { + $this->expectException(NotPermittedException::class); $this->view->expects($this->any()) ->method('getFileInfo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_READ])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_READ])); $this->view->expects($this->never()) ->method('rename'); $node = $this->createTestNode($this->root, $this->view, '/bar/foo'); - $parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar'); + $parentNode = new Folder($this->root, $this->view, '/bar'); $this->root->expects($this->once()) ->method('get') @@ -696,11 +706,11 @@ abstract class NodeTest extends \Test\TestCase { } - public function testMoveNoParent() { - $this->expectException(\OCP\Files\NotFoundException::class); + public function testMoveNoParent(): void { + $this->expectException(NotFoundException::class); /** - * @var \OC\Files\Storage\Storage | \PHPUnit\Framework\MockObject\MockObject $storage + * @var Storage|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->createMock('\OC\Files\Storage\Storage'); @@ -712,20 +722,20 @@ abstract class NodeTest extends \Test\TestCase { $this->root->expects($this->once()) ->method('get') ->with('/bar') - ->will($this->throwException(new NotFoundException())); + ->willThrowException(new NotFoundException()); $node->move('/bar/asd'); } - public function testMoveParentIsFile() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testMoveParentIsFile(): void { + $this->expectException(NotPermittedException::class); $this->view->expects($this->never()) ->method('rename'); $node = $this->createTestNode($this->root, $this->view, '/bar/foo'); - $parentNode = new \OC\Files\Node\File($this->root, $this->view, '/bar'); + $parentNode = new File($this->root, $this->view, '/bar'); $this->root->expects($this->once()) ->method('get') @@ -736,8 +746,8 @@ abstract class NodeTest extends \Test\TestCase { } - public function testMoveFailed() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testMoveFailed(): void { + $this->expectException(NotPermittedException::class); $this->view->expects($this->any()) ->method('rename') @@ -746,10 +756,10 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->any()) ->method('getFileInfo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL, 'fileid' => 1])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL, 'fileid' => 1])); $node = $this->createTestNode($this->root, $this->view, '/bar/foo'); - $parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar'); + $parentNode = new Folder($this->root, $this->view, '/bar'); $this->root->expects($this->any()) ->method('get') @@ -759,8 +769,8 @@ abstract class NodeTest extends \Test\TestCase { } - public function testCopyFailed() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testCopyFailed(): void { + $this->expectException(NotPermittedException::class); $this->view->expects($this->any()) ->method('copy') @@ -769,10 +779,10 @@ abstract class NodeTest extends \Test\TestCase { $this->view->expects($this->any()) ->method('getFileInfo') - ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL, 'fileid' => 1])); + ->willReturn($this->getFileInfo(['permissions' => Constants::PERMISSION_ALL, 'fileid' => 1])); $node = $this->createTestNode($this->root, $this->view, '/bar/foo'); - $parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar'); + $parentNode = new Folder($this->root, $this->view, '/bar'); $this->root->expects($this->any()) ->method('get') diff --git a/tests/lib/Files/Node/RootTest.php b/tests/lib/Files/Node/RootTest.php index 9b3139cf78b..d90e6a2cc6e 100644 --- a/tests/lib/Files/Node/RootTest.php +++ b/tests/lib/Files/Node/RootTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -10,10 +11,17 @@ namespace Test\Files\Node; use OC\Files\FileInfo; use OC\Files\Mount\Manager; use OC\Files\Node\Folder; +use OC\Files\Node\Root; +use OC\Files\Storage\Storage; use OC\Files\View; use OC\Memcache\ArrayCache; +use OC\User\NoUserException; +use OC\User\User; use OCP\Cache\CappedMemoryCache; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Config\IUserMountCache; +use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; use OCP\ICacheFactory; use OCP\IUser; use OCP\IUserManager; @@ -25,11 +33,11 @@ use Psr\Log\LoggerInterface; * @package Test\Files\Node */ class RootTest extends \Test\TestCase { - /** @var \OC\User\User */ + /** @var User */ private $user; /** @var \OC\Files\Mount\Manager */ private $manager; - /** @var \OCP\Files\Config\IUserMountCache|\PHPUnit\Framework\MockObject\MockObject */ + /** @var IUserMountCache|\PHPUnit\Framework\MockObject\MockObject */ private $userMountCache; /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ private $logger; @@ -61,7 +69,7 @@ class RootTest extends \Test\TestCase { } /** - * @return \OC\Files\View | \PHPUnit\Framework\MockObject\MockObject $view + * @return View|\PHPUnit\Framework\MockObject\MockObject $view */ protected function getRootViewMock() { $view = $this->createMock(View::class); @@ -75,15 +83,15 @@ class RootTest extends \Test\TestCase { return new FileInfo('', null, '', $data, null); } - public function testGet() { + public function testGet(): void { /** - * @var \OC\Files\Storage\Storage $storage + * @var Storage $storage */ $storage = $this->getMockBuilder('\OC\Files\Storage\Storage') ->disableOriginalConstructor() ->getMock(); $view = $this->getRootViewMock(); - $root = new \OC\Files\Node\Root( + $root = new Root( $this->manager, $view, $this->user, @@ -106,17 +114,17 @@ class RootTest extends \Test\TestCase { } - public function testGetNotFound() { - $this->expectException(\OCP\Files\NotFoundException::class); + public function testGetNotFound(): void { + $this->expectException(NotFoundException::class); /** - * @var \OC\Files\Storage\Storage $storage + * @var Storage $storage */ $storage = $this->getMockBuilder('\OC\Files\Storage\Storage') ->disableOriginalConstructor() ->getMock(); $view = $this->getRootViewMock(); - $root = new \OC\Files\Node\Root( + $root = new Root( $this->manager, $view, $this->user, @@ -137,11 +145,11 @@ class RootTest extends \Test\TestCase { } - public function testGetInvalidPath() { - $this->expectException(\OCP\Files\NotPermittedException::class); + public function testGetInvalidPath(): void { + $this->expectException(NotPermittedException::class); $view = $this->getRootViewMock(); - $root = new \OC\Files\Node\Root( + $root = new Root( $this->manager, $view, $this->user, @@ -156,11 +164,11 @@ class RootTest extends \Test\TestCase { } - public function testGetNoStorages() { - $this->expectException(\OCP\Files\NotFoundException::class); + public function testGetNoStorages(): void { + $this->expectException(NotFoundException::class); $view = $this->getRootViewMock(); - $root = new \OC\Files\Node\Root( + $root = new Root( $this->manager, $view, $this->user, @@ -174,8 +182,8 @@ class RootTest extends \Test\TestCase { $root->get('/bar/foo'); } - public function testGetUserFolder() { - $root = new \OC\Files\Node\Root( + public function testGetUserFolder(): void { + $root = new Root( $this->manager, $this->getRootViewMock(), $this->user, @@ -213,11 +221,11 @@ class RootTest extends \Test\TestCase { } - public function testGetUserFolderWithNoUserObj() { - $this->expectException(\OC\User\NoUserException::class); + public function testGetUserFolderWithNoUserObj(): void { + $this->expectException(NoUserException::class); $this->expectExceptionMessage('Backends provided no user object'); - $root = new \OC\Files\Node\Root( + $root = new Root( $this->createMock(Manager::class), $this->getRootViewMock(), null, diff --git a/tests/lib/Files/ObjectStore/AzureTest.php b/tests/lib/Files/ObjectStore/AzureTest.php index 5d4234532a6..52d2b9e8657 100644 --- a/tests/lib/Files/ObjectStore/AzureTest.php +++ b/tests/lib/Files/ObjectStore/AzureTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -7,13 +8,15 @@ namespace Test\Files\ObjectStore; use OC\Files\ObjectStore\Azure; +use OCP\IConfig; +use OCP\Server; /** * @group PRIMARY-azure */ -class AzureTest extends ObjectStoreTest { +class AzureTest extends ObjectStoreTestCase { protected function getInstance() { - $config = \OC::$server->getConfig()->getSystemValue('objectstore'); + $config = Server::get(IConfig::class)->getSystemValue('objectstore'); if (!is_array($config) || $config['class'] !== 'OC\\Files\\ObjectStore\\Azure') { $this->markTestSkipped('objectstore not configured for azure'); } @@ -21,7 +24,7 @@ class AzureTest extends ObjectStoreTest { return new Azure($config['arguments']); } - public function testFseekSize() { + public function testFseekSize(): void { $this->markTestSkipped('azure does not support seeking at the moment'); } } diff --git a/tests/lib/Files/ObjectStore/FailDeleteObjectStore.php b/tests/lib/Files/ObjectStore/FailDeleteObjectStore.php index b84ee1a1b64..767125d42aa 100644 --- a/tests/lib/Files/ObjectStore/FailDeleteObjectStore.php +++ b/tests/lib/Files/ObjectStore/FailDeleteObjectStore.php @@ -11,10 +11,9 @@ namespace Test\Files\ObjectStore; use OCP\Files\ObjectStore\IObjectStore; class FailDeleteObjectStore implements IObjectStore { - private $objectStore; - - public function __construct(IObjectStore $objectStore) { - $this->objectStore = $objectStore; + public function __construct( + private IObjectStore $objectStore, + ) { } public function getStorageId() { diff --git a/tests/lib/Files/ObjectStore/FailWriteObjectStore.php b/tests/lib/Files/ObjectStore/FailWriteObjectStore.php index b84b123244e..924bbdada4f 100644 --- a/tests/lib/Files/ObjectStore/FailWriteObjectStore.php +++ b/tests/lib/Files/ObjectStore/FailWriteObjectStore.php @@ -11,10 +11,9 @@ namespace Test\Files\ObjectStore; use OCP\Files\ObjectStore\IObjectStore; class FailWriteObjectStore implements IObjectStore { - private $objectStore; - - public function __construct(IObjectStore $objectStore) { - $this->objectStore = $objectStore; + public function __construct( + private IObjectStore $objectStore, + ) { } public function getStorageId() { diff --git a/tests/lib/Files/ObjectStore/LocalTest.php b/tests/lib/Files/ObjectStore/LocalTest.php index 99c5b61534f..d3e9ad56164 100644 --- a/tests/lib/Files/ObjectStore/LocalTest.php +++ b/tests/lib/Files/ObjectStore/LocalTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -8,10 +9,11 @@ namespace Test\Files\ObjectStore; use OC\Files\ObjectStore\StorageObjectStore; use OC\Files\Storage\Temporary; +use OCP\Files\ObjectStore\IObjectStore; -class LocalTest extends ObjectStoreTest { +class LocalTest extends ObjectStoreTestCase { /** - * @return \OCP\Files\ObjectStore\IObjectStore + * @return IObjectStore */ protected function getInstance() { $storage = new Temporary(); diff --git a/tests/lib/Files/ObjectStore/MapperTest.php b/tests/lib/Files/ObjectStore/MapperTest.php index 19269f13355..6448d5ce1f5 100644 --- a/tests/lib/Files/ObjectStore/MapperTest.php +++ b/tests/lib/Files/ObjectStore/MapperTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -29,7 +30,7 @@ class MapperTest extends \Test\TestCase { $this->mapper = new Mapper($this->user, $this->config); } - public function dataGetBucket() { + public static function dataGetBucket(): array { return [ ['user', 64, 0, '17'], ['USER', 64, 0, '0'], @@ -42,12 +43,12 @@ class MapperTest extends \Test\TestCase { } /** - * @dataProvider dataGetBucket * @param string $username * @param int $numBuckets * @param string $expectedBucket */ - public function testGetBucket($username, $numBuckets, $bucketShift, $expectedBucket) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetBucket')] + public function testGetBucket($username, $numBuckets, $bucketShift, $expectedBucket): void { $this->user->expects($this->once()) ->method('getUID') ->willReturn($username); diff --git a/tests/lib/Files/ObjectStore/ObjectStoreScannerTest.php b/tests/lib/Files/ObjectStore/ObjectStoreScannerTest.php index 425dc8c2581..ea6ac682c70 100644 --- a/tests/lib/Files/ObjectStore/ObjectStoreScannerTest.php +++ b/tests/lib/Files/ObjectStore/ObjectStoreScannerTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -31,13 +32,11 @@ class ObjectStoreScannerTest extends TestCase { $this->realScanner = new Scanner($this->storage); } - public function testFile() { + public function testFile(): void { $data = "dummy file data\n"; $this->storage->file_put_contents('foo.txt', $data); - $this->assertEquals( - [], - $this->scanner->scanFile('foo.txt'), + $this->assertNull($this->scanner->scanFile('foo.txt'), 'Asserting that no error occurred while scanFile()' ); } @@ -51,17 +50,16 @@ class ObjectStoreScannerTest extends TestCase { $this->storage->file_put_contents('folder/bar.txt', $textData); } - public function testFolder() { + public function testFolder(): void { $this->fillTestFolders(); - $this->assertEquals( - [], + $this->assertNull( $this->scanner->scan(''), 'Asserting that no error occurred while scan()' ); } - public function testBackgroundScan() { + public function testBackgroundScan(): void { $this->fillTestFolders(); $this->storage->mkdir('folder2'); $this->storage->file_put_contents('folder2/bar.txt', 'foobar'); diff --git a/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php b/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php index 8ffd27f0069..3387808445a 100644 --- a/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php +++ b/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -10,6 +11,7 @@ namespace Test\Files\ObjectStore; use OC\Files\ObjectStore\StorageObjectStore; use OC\Files\Storage\Temporary; use OC\Files\Storage\Wrapper\Jail; +use OCP\Constants; use OCP\Files\ObjectStore\IObjectStore; use Test\Files\Storage\Storage; @@ -43,7 +45,7 @@ class ObjectStoreStorageTest extends Storage { parent::tearDown(); } - public function testStat() { + public function testStat(): void { $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; $ctimeStart = time(); $this->instance->file_put_contents('/lorem.txt', file_get_contents($textFile)); @@ -67,29 +69,27 @@ class ObjectStoreStorageTest extends Storage { } } - public function testCheckUpdate() { + public function testCheckUpdate(): void { $this->markTestSkipped('Detecting external changes is not supported on object storages'); } - /** - * @dataProvider copyAndMoveProvider - */ - public function testMove($source, $target) { + #[\PHPUnit\Framework\Attributes\DataProvider('copyAndMoveProvider')] + public function testMove($source, $target): void { $this->initSourceAndTarget($source); - $sourceId = $this->instance->getCache()->getId(ltrim('/', $source)); + $sourceId = $this->instance->getCache()->getId(ltrim($source, '/')); $this->assertNotEquals(-1, $sourceId); $this->instance->rename($source, $target); - $this->assertTrue($this->instance->file_exists($target), $target.' was not created'); - $this->assertFalse($this->instance->file_exists($source), $source.' still exists'); + $this->assertTrue($this->instance->file_exists($target), $target . ' was not created'); + $this->assertFalse($this->instance->file_exists($source), $source . ' still exists'); $this->assertSameAsLorem($target); - $targetId = $this->instance->getCache()->getId(ltrim('/', $target)); + $targetId = $this->instance->getCache()->getId(ltrim($target, '/')); $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); } - public function testRenameDirectory() { + public function testRenameDirectory(): void { $this->instance->mkdir('source'); $this->instance->file_put_contents('source/test1.txt', 'foo'); $this->instance->file_put_contents('source/test2.txt', 'qwerty'); @@ -118,7 +118,7 @@ class ObjectStoreStorageTest extends Storage { $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); } - public function testRenameOverWriteDirectory() { + public function testRenameOverWriteDirectory(): void { $this->instance->mkdir('source'); $this->instance->file_put_contents('source/test1.txt', 'foo'); $sourceId = $this->instance->getCache()->getId('source'); @@ -138,7 +138,7 @@ class ObjectStoreStorageTest extends Storage { $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); } - public function testRenameOverWriteDirectoryOverFile() { + public function testRenameOverWriteDirectoryOverFile(): void { $this->instance->mkdir('source'); $this->instance->file_put_contents('source/test1.txt', 'foo'); $sourceId = $this->instance->getCache()->getId('source'); @@ -155,7 +155,7 @@ class ObjectStoreStorageTest extends Storage { $this->assertSame($sourceId, $targetId, 'fileid must be stable on move or shares will break'); } - public function testWriteObjectSilentFailure() { + public function testWriteObjectSilentFailure(): void { $objectStore = $this->instance->getObjectStore(); $this->instance->setObjectStore(new FailWriteObjectStore($objectStore)); @@ -168,7 +168,7 @@ class ObjectStoreStorageTest extends Storage { $this->assertFalse($this->instance->file_exists('test.txt')); } - public function testWriteObjectSilentFailureNoCheck() { + public function testWriteObjectSilentFailureNoCheck(): void { $objectStore = $this->instance->getObjectStore(); $this->instance->setObjectStore(new FailWriteObjectStore($objectStore)); $this->instance->setValidateWrites(false); @@ -177,7 +177,7 @@ class ObjectStoreStorageTest extends Storage { $this->assertTrue($this->instance->file_exists('test.txt')); } - public function testDeleteObjectFailureKeepCache() { + public function testDeleteObjectFailureKeepCache(): void { $objectStore = $this->instance->getObjectStore(); $this->instance->setObjectStore(new FailDeleteObjectStore($objectStore)); $cache = $this->instance->getCache(); @@ -202,7 +202,7 @@ class ObjectStoreStorageTest extends Storage { $this->assertTrue($cache->inCache('foo/test.txt')); } - public function testCopyBetweenJails() { + public function testCopyBetweenJails(): void { $this->instance->mkdir('a'); $this->instance->mkdir('b'); $jailA = new Jail([ @@ -225,26 +225,26 @@ class ObjectStoreStorageTest extends Storage { $this->assertEquals('3', $this->instance->file_get_contents('b/target/sub/3.txt')); } - public function testCopyPreservesPermissions() { + public function testCopyPreservesPermissions(): void { $cache = $this->instance->getCache(); $this->instance->file_put_contents('test.txt', 'foo'); $this->assertTrue($cache->inCache('test.txt')); - $cache->update($cache->getId('test.txt'), ['permissions' => \OCP\Constants::PERMISSION_READ]); - $this->assertEquals(\OCP\Constants::PERMISSION_READ, $this->instance->getPermissions('test.txt')); + $cache->update($cache->getId('test.txt'), ['permissions' => Constants::PERMISSION_READ]); + $this->assertEquals(Constants::PERMISSION_READ, $this->instance->getPermissions('test.txt')); $this->assertTrue($this->instance->copy('test.txt', 'new.txt')); $this->assertTrue($cache->inCache('new.txt')); - $this->assertEquals(\OCP\Constants::PERMISSION_READ, $this->instance->getPermissions('new.txt')); + $this->assertEquals(Constants::PERMISSION_READ, $this->instance->getPermissions('new.txt')); } /** * Test that copying files will drop permissions like local storage does * TODO: Drop this and fix local storage */ - public function testCopyGrantsPermissions() { + public function testCopyGrantsPermissions(): void { $config['objectstore'] = $this->objectStorage; $config['handleCopiesAsOwned'] = true; $instance = new ObjectStoreStorageOverwrite($config); @@ -254,12 +254,25 @@ class ObjectStoreStorageTest extends Storage { $instance->file_put_contents('test.txt', 'foo'); $this->assertTrue($cache->inCache('test.txt')); - $cache->update($cache->getId('test.txt'), ['permissions' => \OCP\Constants::PERMISSION_READ]); - $this->assertEquals(\OCP\Constants::PERMISSION_READ, $instance->getPermissions('test.txt')); + $cache->update($cache->getId('test.txt'), ['permissions' => Constants::PERMISSION_READ]); + $this->assertEquals(Constants::PERMISSION_READ, $instance->getPermissions('test.txt')); $this->assertTrue($instance->copy('test.txt', 'new.txt')); $this->assertTrue($cache->inCache('new.txt')); - $this->assertEquals(\OCP\Constants::PERMISSION_ALL, $instance->getPermissions('new.txt')); + $this->assertEquals(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/Files/ObjectStore/ObjectStoreStoragesDifferentBucketTest.php b/tests/lib/Files/ObjectStore/ObjectStoreStoragesDifferentBucketTest.php new file mode 100644 index 00000000000..d39426ee821 --- /dev/null +++ b/tests/lib/Files/ObjectStore/ObjectStoreStoragesDifferentBucketTest.php @@ -0,0 +1,43 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace Test\Files\ObjectStore; + +use OC\Files\ObjectStore\StorageObjectStore; +use OC\Files\Storage\Temporary; +use OCP\Files\ObjectStore\IObjectStore; +use Test\Files\Storage\StoragesTestCase; + +/** + * @group DB + */ +class ObjectStoreStoragesDifferentBucketTest extends StoragesTestCase { + /** + * @var IObjectStore + */ + private $objectStore1; + + /** + * @var IObjectStore + */ + private $objectStore2; + + protected function setUp(): void { + parent::setUp(); + + $baseStorage1 = new Temporary(); + $this->objectStore1 = new StorageObjectStore($baseStorage1); + $config['objectstore'] = $this->objectStore1; + $this->storage1 = new ObjectStoreStorageOverwrite($config); + + $baseStorage2 = new Temporary(); + $this->objectStore2 = new StorageObjectStore($baseStorage2); + $config['objectstore'] = $this->objectStore2; + $this->storage2 = new ObjectStoreStorageOverwrite($config); + } +} diff --git a/tests/lib/Files/ObjectStore/ObjectStoreStoragesSameBucketTest.php b/tests/lib/Files/ObjectStore/ObjectStoreStoragesSameBucketTest.php new file mode 100644 index 00000000000..4e42668cd3f --- /dev/null +++ b/tests/lib/Files/ObjectStore/ObjectStoreStoragesSameBucketTest.php @@ -0,0 +1,35 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace Test\Files\ObjectStore; + +use OC\Files\ObjectStore\StorageObjectStore; +use OC\Files\Storage\Temporary; +use OCP\Files\ObjectStore\IObjectStore; +use Test\Files\Storage\StoragesTestCase; + +/** + * @group DB + */ +class ObjectStoreStoragesSameBucketTest extends StoragesTestCase { + /** + * @var IObjectStore + */ + private $objectStore; + + protected function setUp(): void { + parent::setUp(); + + $baseStorage = new Temporary(); + $this->objectStore = new StorageObjectStore($baseStorage); + $config['objectstore'] = $this->objectStore; + // storage1 and storage2 share the same object store. + $this->storage1 = new ObjectStoreStorageOverwrite($config); + $this->storage2 = new ObjectStoreStorageOverwrite($config); + } +} diff --git a/tests/lib/Files/ObjectStore/ObjectStoreTest.php b/tests/lib/Files/ObjectStore/ObjectStoreTestCase.php index 74f047a8663..03e7b9545e0 100644 --- a/tests/lib/Files/ObjectStore/ObjectStoreTest.php +++ b/tests/lib/Files/ObjectStore/ObjectStoreTestCase.php @@ -7,14 +7,17 @@ namespace Test\Files\ObjectStore; +use OCP\Files\ObjectStore\IObjectStore; use Test\TestCase; -abstract class ObjectStoreTest extends TestCase { +abstract class ObjectStoreTestCase extends TestCase { /** @var string[] */ private $cleanup = []; + private $instance = null; + /** - * @return \OCP\Files\ObjectStore\IObjectStore + * @return IObjectStore */ abstract protected function getInstance(); @@ -22,13 +25,20 @@ abstract class ObjectStoreTest extends TestCase { $this->cleanup[] = $urn; } - public function tearDown(): void { - parent::tearDown(); + public function setUp(): void { + parent::setUp(); - $instance = $this->getInstance(); - foreach ($this->cleanup as $urn) { - $instance->deleteObject($urn); + $this->instance = $this->getInstance(); + } + + public function tearDown(): void { + if ($this->instance) { + foreach ($this->cleanup as $urn) { + $this->instance->deleteObject($urn); + } } + + parent::tearDown(); } protected function stringToStream($data) { @@ -38,7 +48,7 @@ abstract class ObjectStoreTest extends TestCase { return $stream; } - public function testWriteRead() { + public function testWriteRead(): void { $stream = $this->stringToStream('foobar'); $instance = $this->getInstance(); @@ -51,7 +61,7 @@ abstract class ObjectStoreTest extends TestCase { $this->assertEquals('foobar', stream_get_contents($result)); } - public function testDelete() { + public function testDelete(): void { $stream = $this->stringToStream('foobar'); $instance = $this->getInstance(); @@ -70,7 +80,7 @@ abstract class ObjectStoreTest extends TestCase { } } - public function testReadNonExisting() { + public function testReadNonExisting(): void { $instance = $this->getInstance(); try { @@ -82,7 +92,7 @@ abstract class ObjectStoreTest extends TestCase { } } - public function testDeleteNonExisting() { + public function testDeleteNonExisting(): void { $instance = $this->getInstance(); try { @@ -94,7 +104,7 @@ abstract class ObjectStoreTest extends TestCase { } } - public function testExists() { + public function testExists(): void { $stream = $this->stringToStream('foobar'); $instance = $this->getInstance(); @@ -109,7 +119,7 @@ abstract class ObjectStoreTest extends TestCase { $this->assertFalse($instance->objectExists('2')); } - public function testCopy() { + public function testCopy(): void { $this->cleanupAfter('source'); $this->cleanupAfter('target'); @@ -128,7 +138,7 @@ abstract class ObjectStoreTest extends TestCase { $this->assertEquals('foobar', stream_get_contents($instance->readObject('target'))); } - public function testFseekSize() { + public function testFseekSize(): void { $instance = $this->getInstance(); $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; diff --git a/tests/lib/Files/ObjectStore/PrimaryObjectStoreConfigTest.php b/tests/lib/Files/ObjectStore/PrimaryObjectStoreConfigTest.php new file mode 100644 index 00000000000..b60b7ca4f83 --- /dev/null +++ b/tests/lib/Files/ObjectStore/PrimaryObjectStoreConfigTest.php @@ -0,0 +1,285 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2025 Robin Appelman <robin@icewind.nl> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace lib\Files\ObjectStore; + +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; +use OC\Files\ObjectStore\StorageObjectStore; +use OCP\App\IAppManager; +use OCP\IConfig; +use OCP\IUser; +use PHPUnit\Framework\MockObject\MockObject; +use Test\TestCase; + +class PrimaryObjectStoreConfigTest extends TestCase { + private array $systemConfig = []; + private array $userConfig = []; + private IConfig&MockObject $config; + private IAppManager&MockObject $appManager; + private PrimaryObjectStoreConfig $objectStoreConfig; + + protected function setUp(): void { + parent::setUp(); + + $this->systemConfig = []; + $this->config = $this->createMock(IConfig::class); + $this->appManager = $this->createMock(IAppManager::class); + $this->config->method('getSystemValue') + ->willReturnCallback(function ($key, $default = '') { + if (isset($this->systemConfig[$key])) { + return $this->systemConfig[$key]; + } else { + return $default; + } + }); + $this->config->method('getUserValue') + ->willReturnCallback(function ($userId, $appName, $key, $default = '') { + if (isset($this->userConfig[$userId][$appName][$key])) { + return $this->userConfig[$userId][$appName][$key]; + } else { + return $default; + } + }); + $this->config->method('setUserValue') + ->willReturnCallback(function ($userId, $appName, $key, $value) { + $this->userConfig[$userId][$appName][$key] = $value; + }); + + $this->objectStoreConfig = new PrimaryObjectStoreConfig($this->config, $this->appManager); + } + + private function getUser(string $uid): IUser { + $user = $this->createMock(IUser::class); + $user->method('getUID') + ->willReturn($uid); + return $user; + } + + private function setConfig(string $key, $value) { + $this->systemConfig[$key] = $value; + } + + public function testNewUserGetsDefault() { + $this->setConfig('objectstore', [ + 'default' => 'server1', + 'server1' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + ], + ], + ]); + + $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test')); + $this->assertEquals('server1', $result['arguments']['host']); + + $this->assertEquals('server1', $this->config->getUserValue('test', 'homeobjectstore', 'objectstore', null)); + } + + public function testExistingUserKeepsStorage() { + // setup user with `server1` as storage + $this->testNewUserGetsDefault(); + + $this->setConfig('objectstore', [ + 'default' => 'server2', + 'server1' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + ], + ], + 'server2' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server2', + ], + ], + ]); + + $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test')); + $this->assertEquals('server1', $result['arguments']['host']); + + $this->assertEquals('server1', $this->config->getUserValue('test', 'homeobjectstore', 'objectstore', null)); + + $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('other-user')); + $this->assertEquals('server2', $result['arguments']['host']); + } + + public function testNestedAliases() { + $this->setConfig('objectstore', [ + 'default' => 'a1', + 'a1' => 'a2', + 'a2' => 'server1', + 'server1' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + ], + ], + ]); + $this->assertEquals('server1', $this->objectStoreConfig->resolveAlias('default')); + } + + public function testMultibucketChangedConfig() { + $this->setConfig('objectstore', [ + 'default' => 'server1', + 'server1' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + 'multibucket' => true, + 'num_buckets' => 8, + 'bucket' => 'bucket-' + ], + ], + ]); + + $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test')); + $this->assertEquals('server1', $result['arguments']['host']); + $this->assertEquals('bucket-7', $result['arguments']['bucket']); + + $this->setConfig('objectstore', [ + 'default' => 'server1', + 'server1' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + 'multibucket' => true, + 'num_buckets' => 64, + 'bucket' => 'bucket-' + ], + ], + ]); + + $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test')); + $this->assertEquals('server1', $result['arguments']['host']); + $this->assertEquals('bucket-7', $result['arguments']['bucket']); + + $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test-foo')); + $this->assertEquals('server1', $result['arguments']['host']); + $this->assertEquals('bucket-40', $result['arguments']['bucket']); + + $this->setConfig('objectstore', [ + 'default' => 'server2', + 'server1' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + 'multibucket' => true, + 'num_buckets' => 64, + 'bucket' => 'bucket-' + ], + ], + 'server2' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server2', + 'multibucket' => true, + 'num_buckets' => 16, + 'bucket' => 'bucket-' + ], + ], + ]); + + $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test')); + $this->assertEquals('server1', $result['arguments']['host']); + $this->assertEquals('bucket-7', $result['arguments']['bucket']); + + $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test-bar')); + $this->assertEquals('server2', $result['arguments']['host']); + $this->assertEquals('bucket-4', $result['arguments']['bucket']); + } + + public function testMultibucketOldConfig() { + $this->setConfig('objectstore_multibucket', [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + 'multibucket' => true, + 'num_buckets' => 8, + 'bucket' => 'bucket-' + ], + ]); + $configs = $this->objectStoreConfig->getObjectStoreConfigs(); + $this->assertEquals([ + 'default' => 'server1', + 'root' => 'server1', + 'server1' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + 'multibucket' => true, + 'num_buckets' => 8, + 'bucket' => 'bucket-' + ], + ], + ], $configs); + } + + public function testSingleObjectStore() { + $this->setConfig('objectstore', [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + ], + ]); + $configs = $this->objectStoreConfig->getObjectStoreConfigs(); + $this->assertEquals([ + 'default' => 'server1', + 'root' => 'server1', + 'server1' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + 'multibucket' => false, + ], + ], + ], $configs); + } + + public function testRoot() { + $this->setConfig('objectstore', [ + 'default' => 'server1', + 'server1' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + ], + ], + 'server2' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server2', + ], + ], + ]); + + $result = $this->objectStoreConfig->getObjectStoreConfigForRoot(); + $this->assertEquals('server1', $result['arguments']['host']); + + $this->setConfig('objectstore', [ + 'default' => 'server1', + 'root' => 'server2', + 'server1' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server1', + ], + ], + 'server2' => [ + 'class' => StorageObjectStore::class, + 'arguments' => [ + 'host' => 'server2', + ], + ], + ]); + + $result = $this->objectStoreConfig->getObjectStoreConfigForRoot(); + $this->assertEquals('server2', $result['arguments']['host']); + } +} diff --git a/tests/lib/Files/ObjectStore/S3Test.php b/tests/lib/Files/ObjectStore/S3Test.php index cc3e91a4586..2915ada0aab 100644 --- a/tests/lib/Files/ObjectStore/S3Test.php +++ b/tests/lib/Files/ObjectStore/S3Test.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -8,6 +9,8 @@ namespace Test\Files\ObjectStore; use Icewind\Streams\Wrapper; use OC\Files\ObjectStore\S3; +use OCP\IConfig; +use OCP\Server; class MultiPartUploadS3 extends S3 { public function writeObject($urn, $stream, ?string $mimetype = null) { @@ -44,7 +47,7 @@ class NonSeekableStream extends Wrapper { /** * @group PRIMARY-s3 */ -class S3Test extends ObjectStoreTest { +class S3Test extends ObjectStoreTestCase { public function setUp(): void { parent::setUp(); $s3 = $this->getInstance(); @@ -52,7 +55,7 @@ class S3Test extends ObjectStoreTest { } protected function getInstance() { - $config = \OC::$server->getConfig()->getSystemValue('objectstore'); + $config = Server::get(IConfig::class)->getSystemValue('objectstore'); if (!is_array($config) || $config['class'] !== S3::class) { $this->markTestSkipped('objectstore not configured for s3'); } @@ -60,7 +63,7 @@ class S3Test extends ObjectStoreTest { return new S3($config['arguments']); } - public function testUploadNonSeekable() { + public function testUploadNonSeekable(): void { $this->cleanupAfter('multiparttest'); $s3 = $this->getInstance(); @@ -72,7 +75,7 @@ class S3Test extends ObjectStoreTest { $this->assertEquals(file_get_contents(__FILE__), stream_get_contents($result)); } - public function testSeek() { + public function testSeek(): void { $this->cleanupAfter('seek'); $data = file_get_contents(__FILE__); @@ -101,10 +104,10 @@ class S3Test extends ObjectStoreTest { $this->assertArrayNotHasKey('Uploads', $uploads, 'Assert is not uploaded'); } - public function testEmptyUpload() { + public function testEmptyUpload(): void { $s3 = $this->getInstance(); - $emptyStream = fopen("php://memory", "r"); + $emptyStream = fopen('php://memory', 'r'); fwrite($emptyStream, ''); $s3->writeObject('emptystream', $emptyStream); @@ -126,14 +129,18 @@ class S3Test extends ObjectStoreTest { } /** File size to upload in bytes */ - public function dataFileSizes() { + public static function dataFileSizes(): array { return [ [1000000], [2000000], [5242879], [5242880], [5242881], [10000000] ]; } - /** @dataProvider dataFileSizes */ - public function testFileSizes($size) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataFileSizes')] + public function testFileSizes($size): void { + if (str_starts_with(PHP_VERSION, '8.3') && getenv('CI')) { + $this->markTestSkipped('Test is unreliable and skipped on 8.3'); + } + $this->cleanupAfter('testfilesizes'); $s3 = $this->getInstance(); diff --git a/tests/lib/Files/ObjectStore/SwiftTest.php b/tests/lib/Files/ObjectStore/SwiftTest.php index 8c9a0d524ed..3f919c0dd48 100644 --- a/tests/lib/Files/ObjectStore/SwiftTest.php +++ b/tests/lib/Files/ObjectStore/SwiftTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -8,16 +9,19 @@ namespace Test\Files\ObjectStore; use OC\Files\ObjectStore\Swift; +use OCP\Files\ObjectStore\IObjectStore; +use OCP\IConfig; +use OCP\Server; /** * @group PRIMARY-swift */ -class SwiftTest extends ObjectStoreTest { +class SwiftTest extends ObjectStoreTestCase { /** - * @return \OCP\Files\ObjectStore\IObjectStore + * @return IObjectStore */ protected function getInstance() { - $config = \OC::$server->getConfig()->getSystemValue('objectstore'); + $config = Server::get(IConfig::class)->getSystemValue('objectstore'); if (!is_array($config) || $config['class'] !== 'OC\\Files\\ObjectStore\\Swift') { $this->markTestSkipped('objectstore not configured for swift'); } @@ -25,7 +29,7 @@ class SwiftTest extends ObjectStoreTest { return new Swift($config['arguments']); } - public function testFseekSize() { + public function testFseekSize(): void { $this->markTestSkipped('Swift does not support seeking at the moment'); } } diff --git a/tests/lib/Files/PathVerificationTest.php b/tests/lib/Files/PathVerificationTest.php index 4addd583354..e13dbe4f207 100644 --- a/tests/lib/Files/PathVerificationTest.php +++ b/tests/lib/Files/PathVerificationTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -10,6 +11,8 @@ namespace Test\Files; use OC\Files\Storage\Local; use OC\Files\View; use OCP\Files\InvalidPathException; +use OCP\IDBConnection; +use OCP\Server; /** * Class PathVerificationTest @@ -20,7 +23,7 @@ use OCP\Files\InvalidPathException; */ class PathVerificationTest extends \Test\TestCase { /** - * @var \OC\Files\View + * @var View */ private $view; @@ -30,43 +33,39 @@ class PathVerificationTest extends \Test\TestCase { } - public function testPathVerificationFileNameTooLong() { - $this->expectException(\OCP\Files\InvalidPathException::class); - $this->expectExceptionMessage('File name is too long'); + public function testPathVerificationFileNameTooLong(): void { + $this->expectException(InvalidPathException::class); + $this->expectExceptionMessage('Filename is too long'); $fileName = str_repeat('a', 500); $this->view->verifyPath('', $fileName); } - /** - * @dataProvider providesEmptyFiles - */ - public function testPathVerificationEmptyFileName($fileName) { - $this->expectException(\OCP\Files\InvalidPathException::class); + #[\PHPUnit\Framework\Attributes\DataProvider('providesEmptyFiles')] + public function testPathVerificationEmptyFileName($fileName): void { + $this->expectException(InvalidPathException::class); $this->expectExceptionMessage('Empty filename is not allowed'); $this->view->verifyPath('', $fileName); } - public function providesEmptyFiles() { + public static function providesEmptyFiles(): array { return [ [''], [' '], ]; } - /** - * @dataProvider providesDotFiles - */ - public function testPathVerificationDotFiles($fileName) { - $this->expectException(\OCP\Files\InvalidPathException::class); + #[\PHPUnit\Framework\Attributes\DataProvider('providesDotFiles')] + public function testPathVerificationDotFiles($fileName): void { + $this->expectException(InvalidPathException::class); $this->expectExceptionMessage('Dot files are not allowed'); $this->view->verifyPath('', $fileName); } - public function providesDotFiles() { + public static function providesDotFiles(): array { return [ ['.'], ['..'], @@ -79,11 +78,9 @@ class PathVerificationTest extends \Test\TestCase { ]; } - /** - * @dataProvider providesAstralPlane - */ - public function testPathVerificationAstralPlane($fileName) { - $connection = \OC::$server->getDatabaseConnection(); + #[\PHPUnit\Framework\Attributes\DataProvider('providesAstralPlane')] + public function testPathVerificationAstralPlane($fileName): void { + $connection = Server::get(IDBConnection::class); if (!$connection->supports4ByteText()) { $this->expectException(InvalidPathException::class); @@ -95,7 +92,7 @@ class PathVerificationTest extends \Test\TestCase { $this->view->verifyPath('', $fileName); } - public function providesAstralPlane() { + public static function providesAstralPlane(): array { return [ // this is the monkey emoji - http://en.wikipedia.org/w/index.php?title=%F0%9F%90%B5&redirect=no ['🐵'], @@ -106,61 +103,8 @@ class PathVerificationTest extends \Test\TestCase { ]; } - /** - * @dataProvider providesInvalidCharsPosix - */ - public function testPathVerificationInvalidCharsPosix($fileName) { - $this->expectException(\OCP\Files\InvalidCharacterInPathException::class); - - $storage = new Local(['datadir' => '']); - - $fileName = " 123{$fileName}456 "; - self::invokePrivate($storage, 'verifyPosixPath', [$fileName]); - } - - public function providesInvalidCharsPosix() { - return [ - [\chr(0)], - [\chr(1)], - [\chr(2)], - [\chr(3)], - [\chr(4)], - [\chr(5)], - [\chr(6)], - [\chr(7)], - [\chr(8)], - [\chr(9)], - [\chr(10)], - [\chr(11)], - [\chr(12)], - [\chr(13)], - [\chr(14)], - [\chr(15)], - [\chr(16)], - [\chr(17)], - [\chr(18)], - [\chr(19)], - [\chr(20)], - [\chr(21)], - [\chr(22)], - [\chr(23)], - [\chr(24)], - [\chr(25)], - [\chr(26)], - [\chr(27)], - [\chr(28)], - [\chr(29)], - [\chr(30)], - [\chr(31)], - ['/'], - ['\\'], - ]; - } - - /** - * @dataProvider providesValidPosixPaths - */ - public function testPathVerificationValidPaths($fileName) { + #[\PHPUnit\Framework\Attributes\DataProvider('providesValidPosixPaths')] + public function testPathVerificationValidPaths($fileName): void { $storage = new Local(['datadir' => '']); self::invokePrivate($storage, 'verifyPosixPath', [$fileName]); @@ -168,7 +112,7 @@ class PathVerificationTest extends \Test\TestCase { $this->addToAssertionCount(1); } - public function providesValidPosixPaths() { + public static function providesValidPosixPaths(): array { return [ ['simple'], ['simple.txt'], diff --git a/tests/lib/Files/Search/QueryOptimizer/CombinedTests.php b/tests/lib/Files/Search/QueryOptimizer/CombinedTests.php index 5c7c01da926..665224cb63e 100644 --- a/tests/lib/Files/Search/QueryOptimizer/CombinedTests.php +++ b/tests/lib/Files/Search/QueryOptimizer/CombinedTests.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -21,21 +22,21 @@ class CombinedTests extends TestCase { $this->optimizer = new QueryOptimizer(); } - public function testBasicOrOfAnds() { + public function testBasicOrOfAnds(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "asd"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'), ]) ] ); @@ -46,35 +47,35 @@ class CombinedTests extends TestCase { $this->assertEquals('(storage eq 1 and path in ["foo","bar","asd"])', $operator->__toString()); } - public function testComplexSearchPattern1() { + public function testComplexSearchPattern1(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 2), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "201"), - new SearchComparison(ISearchComparison::COMPARE_LIKE, "path", "201/%"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '201'), + new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', '201/%'), ]), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 3), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "301"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '301'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 4), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "401"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 4), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '401'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 3), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "302"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '302'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 4), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "402"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 4), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '402'), ]), ] ); @@ -85,33 +86,33 @@ class CombinedTests extends TestCase { $this->assertEquals('(storage eq 1 or (storage eq 2 and (path eq "201" or path like "201\/%")) or (storage eq 3 and path in ["301","302"]) or (storage eq 4 and path in ["401","402"]))', $operator->__toString()); } - public function testComplexSearchPattern2() { + public function testComplexSearchPattern2(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 2), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "201"), - new SearchComparison(ISearchComparison::COMPARE_LIKE, "path", "201/%"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '201'), + new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', '201/%'), ]), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 3), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "301"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '301'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 4), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "401"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 4), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '401'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 3), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "302"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '302'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 4), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "402"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 4), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '402'), ]), ] ); @@ -122,30 +123,30 @@ class CombinedTests extends TestCase { $this->assertEquals('(storage eq 1 or (storage eq 2 and (path eq "201" or path like "201\/%")) or (storage eq 3 and path in ["301","302"]) or (storage eq 4 and path in ["401","402"]))', $operator->__toString()); } - public function testApplySearchConstraints1() { + public function testApplySearchConstraints1(): void { $operator = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "mimetype", "image/png"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "mimetype", "image/jpeg"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'image/png'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'image/jpeg'), ]), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "files"), - new SearchComparison(ISearchComparison::COMPARE_LIKE, "path", "files/%"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files'), + new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', 'files/%'), ]), ]), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 2), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 3), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "files/301"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files/301'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 3), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "files/302"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files/302'), ]), ]), ]); @@ -156,32 +157,32 @@ class CombinedTests extends TestCase { $this->assertEquals('(mimetype in ["image\/png","image\/jpeg"] and ((storage eq 1 and (path eq "files" or path like "files\/%")) or storage eq 2 or (storage eq 3 and path in ["files\/301","files\/302"])))', $operator->__toString()); } - public function testApplySearchConstraints2() { + public function testApplySearchConstraints2(): void { $operator = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "mimetype", "image/png"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "mimetype", "image/jpeg"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'image/png'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'image/jpeg'), ]), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "files"), - new SearchComparison(ISearchComparison::COMPARE_LIKE, "path", "files/%"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files'), + new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', 'files/%'), ]), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 2), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 3), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "files/301"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files/301'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 3), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "files/302"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files/302'), ]), ]), ]); diff --git a/tests/lib/Files/Search/QueryOptimizer/FlattenNestedBoolTest.php b/tests/lib/Files/Search/QueryOptimizer/FlattenNestedBoolTest.php index 538ffc65f02..1d43541a5a0 100644 --- a/tests/lib/Files/Search/QueryOptimizer/FlattenNestedBoolTest.php +++ b/tests/lib/Files/Search/QueryOptimizer/FlattenNestedBoolTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -24,14 +25,14 @@ class FlattenNestedBoolTest extends TestCase { $this->simplifier = new FlattenSingleArgumentBinaryOperation(); } - public function testOrs() { + public function testOrs(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "asd"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'), ]) ] ); diff --git a/tests/lib/Files/Search/QueryOptimizer/MergeDistributiveOperationsTest.php b/tests/lib/Files/Search/QueryOptimizer/MergeDistributiveOperationsTest.php index abc9eca9a54..9aaa7030aac 100644 --- a/tests/lib/Files/Search/QueryOptimizer/MergeDistributiveOperationsTest.php +++ b/tests/lib/Files/Search/QueryOptimizer/MergeDistributiveOperationsTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -24,21 +25,21 @@ class MergeDistributiveOperationsTest extends TestCase { $this->simplifier = new FlattenSingleArgumentBinaryOperation(); } - public function testBasicOrOfAnds() { + public function testBasicOrOfAnds(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "asd"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'), ]) ] ); @@ -50,21 +51,21 @@ class MergeDistributiveOperationsTest extends TestCase { $this->assertEquals('(storage eq 1 and (path eq "foo" or path eq "bar" or path eq "asd"))', $operator->__toString()); } - public function testDontTouchIfNotSame() { + public function testDontTouchIfNotSame(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 2), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 3), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "asd"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'), ]) ] ); @@ -76,21 +77,21 @@ class MergeDistributiveOperationsTest extends TestCase { $this->assertEquals('((storage eq 1 and path eq "foo") or (storage eq 2 and path eq "bar") or (storage eq 3 and path eq "asd"))', $operator->__toString()); } - public function testMergePartial() { + public function testMergePartial(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 2), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "asd"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'), ]) ] ); @@ -102,7 +103,7 @@ class MergeDistributiveOperationsTest extends TestCase { $this->assertEquals('((storage eq 1 and (path eq "foo" or path eq "bar")) or (storage eq 2 and path eq "asd"))', $operator->__toString()); } - public function testOptimizeInside() { + public function testOptimizeInside(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_AND, [ @@ -110,20 +111,20 @@ class MergeDistributiveOperationsTest extends TestCase { ISearchBinaryOperator::OPERATOR_OR, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "asd"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'), ]) ] ), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "mimetype", "text") + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'text') ] ); $this->assertEquals('(((storage eq 1 and path eq "foo") or (storage eq 1 and path eq "bar") or (storage eq 1 and path eq "asd")) and mimetype eq "text")', $operator->__toString()); @@ -134,22 +135,22 @@ class MergeDistributiveOperationsTest extends TestCase { $this->assertEquals('((storage eq 1 and (path eq "foo" or path eq "bar" or path eq "asd")) and mimetype eq "text")', $operator->__toString()); } - public function testMoveInnerOperations() { + public function testMoveInnerOperations(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), ]), new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "storage", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "asd"), - new SearchComparison(ISearchComparison::COMPARE_GREATER_THAN, "size", "100"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'), + new SearchComparison(ISearchComparison::COMPARE_GREATER_THAN, 'size', '100'), ]) ] ); diff --git a/tests/lib/Files/Search/QueryOptimizer/OrEqualsToInTest.php b/tests/lib/Files/Search/QueryOptimizer/OrEqualsToInTest.php index 5ea27eb88b9..d51fe3d0d16 100644 --- a/tests/lib/Files/Search/QueryOptimizer/OrEqualsToInTest.php +++ b/tests/lib/Files/Search/QueryOptimizer/OrEqualsToInTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -24,13 +25,13 @@ class OrEqualsToInTest extends TestCase { $this->simplifier = new FlattenSingleArgumentBinaryOperation(); } - public function testOrs() { + public function testOrs(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "asd"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'), ] ); $this->assertEquals('(path eq "foo" or path eq "bar" or path eq "asd")', $operator->__toString()); @@ -41,15 +42,15 @@ class OrEqualsToInTest extends TestCase { $this->assertEquals('path in ["foo","bar","asd"]', $operator->__toString()); } - public function testOrsMultipleFields() { + public function testOrsMultipleFields(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "fileid", 1), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "fileid", 2), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "mimetype", "asd"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'fileid', 1), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'fileid', 2), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'asd'), ] ); $this->assertEquals('(path eq "foo" or path eq "bar" or fileid eq 1 or fileid eq 2 or mimetype eq "asd")', $operator->__toString()); @@ -60,13 +61,13 @@ class OrEqualsToInTest extends TestCase { $this->assertEquals('(path in ["foo","bar"] or fileid in [1,2] or mimetype eq "asd")', $operator->__toString()); } - public function testPreserveHints() { + public function testPreserveHints(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "asd"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'), ] ); foreach ($operator->getArguments() as $argument) { @@ -81,13 +82,13 @@ class OrEqualsToInTest extends TestCase { $this->assertEquals(false, $operator->getQueryHint(ISearchComparison::HINT_PATH_EQ_HASH, true)); } - public function testOrSomeEq() { + public function testOrSomeEq(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), - new SearchComparison(ISearchComparison::COMPARE_LIKE, "path", "foo%"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), + new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', 'foo%'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), ] ); $this->assertEquals('(path eq "foo" or path like "foo%" or path eq "bar")', $operator->__toString()); @@ -98,17 +99,17 @@ class OrEqualsToInTest extends TestCase { $this->assertEquals('(path in ["foo","bar"] or path like "foo%")', $operator->__toString()); } - public function testOrsInside() { + public function testOrsInside(): void { $operator = new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_AND, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "mimetype", "text"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'text'), new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_OR, [ - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "foo"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "bar"), - new SearchComparison(ISearchComparison::COMPARE_EQUAL, "path", "asd"), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'), + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'), ] ) ] diff --git a/tests/lib/Files/Search/SearchIntegrationTest.php b/tests/lib/Files/Search/SearchIntegrationTest.php index b24f927219e..e3e99bbfadd 100644 --- a/tests/lib/Files/Search/SearchIntegrationTest.php +++ b/tests/lib/Files/Search/SearchIntegrationTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -29,12 +30,12 @@ class SearchIntegrationTest extends TestCase { } - public function testThousandAndOneFilters() { - $id = $this->cache->put("file10", ['size' => 1, 'mtime' => 50, 'mimetype' => 'foo/folder']); + public function testThousandAndOneFilters(): void { + $id = $this->cache->put('file10', ['size' => 1, 'mtime' => 50, 'mimetype' => 'foo/folder']); $comparisons = []; - for($i = 1; $i <= 1001; $i++) { - $comparisons[] = new SearchComparison(ISearchComparison::COMPARE_EQUAL, "name", "file$i"); + for ($i = 1; $i <= 1001; $i++) { + $comparisons[] = new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'name', "file$i"); } $operator = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $comparisons); $query = new SearchQuery($operator, 10, 0, []); diff --git a/tests/lib/Files/SimpleFS/InMemoryFileTest.php b/tests/lib/Files/SimpleFS/InMemoryFileTest.php index dfd6c44ac7e..43587acdce9 100644 --- a/tests/lib/Files/SimpleFS/InMemoryFileTest.php +++ b/tests/lib/Files/SimpleFS/InMemoryFileTest.php @@ -44,7 +44,7 @@ class InMemoryFileTest extends TestCase { * * @return void */ - public function testPutContent() { + public function testPutContent(): void { $this->testPdf->putContent('test'); self::assertEquals('test', $this->testPdf->getContent()); } @@ -54,7 +54,7 @@ class InMemoryFileTest extends TestCase { * * @return void */ - public function testDelete() { + public function testDelete(): void { $this->testPdf->delete(); // assert true, otherwise phpunit complains about not doing any assert self::assertTrue(true); @@ -65,7 +65,7 @@ class InMemoryFileTest extends TestCase { * * @return void */ - public function testGetName() { + public function testGetName(): void { self::assertEquals('test.pdf', $this->testPdf->getName()); } @@ -74,7 +74,7 @@ class InMemoryFileTest extends TestCase { * * @return void */ - public function testGetSize() { + public function testGetSize(): void { self::assertEquals(7083, $this->testPdf->getSize()); } @@ -83,7 +83,7 @@ class InMemoryFileTest extends TestCase { * * @return void */ - public function testGetContent() { + public function testGetContent(): void { self::assertEquals( file_get_contents(__DIR__ . '/../../../data/test.pdf'), $this->testPdf->getContent() @@ -95,7 +95,7 @@ class InMemoryFileTest extends TestCase { * * @return void */ - public function testGetMTime() { + public function testGetMTime(): void { self::assertTrue(is_int($this->testPdf->getMTime())); } @@ -104,7 +104,7 @@ class InMemoryFileTest extends TestCase { * * @return void */ - public function testGetMimeType() { + public function testGetMimeType(): void { self::assertEquals('application/pdf', $this->testPdf->getMimeType()); } @@ -114,7 +114,7 @@ class InMemoryFileTest extends TestCase { * * @return void */ - public function testRead() { + public function testRead(): void { self::expectException(NotPermittedException::class); $this->testPdf->read(); } @@ -124,7 +124,7 @@ class InMemoryFileTest extends TestCase { * * @return void */ - public function testWrite() { + public function testWrite(): void { self::expectException(NotPermittedException::class); $this->testPdf->write(); } diff --git a/tests/lib/Files/SimpleFS/SimpleFileTest.php b/tests/lib/Files/SimpleFS/SimpleFileTest.php index 6dbd663068e..6ce5ddad351 100644 --- a/tests/lib/Files/SimpleFS/SimpleFileTest.php +++ b/tests/lib/Files/SimpleFS/SimpleFileTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -25,7 +26,7 @@ class SimpleFileTest extends \Test\TestCase { $this->simpleFile = new SimpleFile($this->file); } - public function testGetName() { + public function testGetName(): void { $this->file->expects($this->once()) ->method('getName') ->willReturn('myname'); @@ -33,7 +34,7 @@ class SimpleFileTest extends \Test\TestCase { $this->assertEquals('myname', $this->simpleFile->getName()); } - public function testGetSize() { + public function testGetSize(): void { $this->file->expects($this->once()) ->method('getSize') ->willReturn(42); @@ -41,7 +42,7 @@ class SimpleFileTest extends \Test\TestCase { $this->assertEquals(42, $this->simpleFile->getSize()); } - public function testGetETag() { + public function testGetETag(): void { $this->file->expects($this->once()) ->method('getETag') ->willReturn('etag'); @@ -49,7 +50,7 @@ class SimpleFileTest extends \Test\TestCase { $this->assertEquals('etag', $this->simpleFile->getETag()); } - public function testGetMTime() { + public function testGetMTime(): void { $this->file->expects($this->once()) ->method('getMTime') ->willReturn(101); @@ -57,7 +58,7 @@ class SimpleFileTest extends \Test\TestCase { $this->assertEquals(101, $this->simpleFile->getMTime()); } - public function testGetContent() { + public function testGetContent(): void { $this->file->expects($this->once()) ->method('getContent') ->willReturn('foo'); @@ -65,7 +66,7 @@ class SimpleFileTest extends \Test\TestCase { $this->assertEquals('foo', $this->simpleFile->getContent()); } - public function testPutContent() { + public function testPutContent(): void { $this->file->expects($this->once()) ->method('putContent') ->with($this->equalTo('bar')); @@ -73,14 +74,14 @@ class SimpleFileTest extends \Test\TestCase { $this->simpleFile->putContent('bar'); } - public function testDelete() { + public function testDelete(): void { $this->file->expects($this->once()) ->method('delete'); $this->simpleFile->delete(); } - public function testGetMimeType() { + public function testGetMimeType(): void { $this->file->expects($this->once()) ->method('getMimeType') ->willReturn('app/awesome'); @@ -88,7 +89,7 @@ class SimpleFileTest extends \Test\TestCase { $this->assertEquals('app/awesome', $this->simpleFile->getMimeType()); } - public function testGetContentInvalidAppData() { + public function testGetContentInvalidAppData(): void { $this->file->method('getContent') ->willReturn(false); $this->file->method('stat')->willReturn(false); @@ -107,7 +108,7 @@ class SimpleFileTest extends \Test\TestCase { $this->simpleFile->getContent(); } - public function testRead() { + public function testRead(): void { $this->file->expects($this->once()) ->method('fopen') ->with('r'); @@ -115,7 +116,7 @@ class SimpleFileTest extends \Test\TestCase { $this->simpleFile->read(); } - public function testWrite() { + public function testWrite(): void { $this->file->expects($this->once()) ->method('fopen') ->with('w'); diff --git a/tests/lib/Files/SimpleFS/SimpleFolderTest.php b/tests/lib/Files/SimpleFS/SimpleFolderTest.php index 139a6cb703c..50038b286a9 100644 --- a/tests/lib/Files/SimpleFS/SimpleFolderTest.php +++ b/tests/lib/Files/SimpleFS/SimpleFolderTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -47,24 +48,24 @@ class SimpleFolderTest extends \Test\TestCase { $this->simpleFolder = new SimpleFolder($this->folder); } - public function testGetName() { + public function testGetName(): void { $this->assertEquals('test', $this->simpleFolder->getName()); } - public function testDelete() { + public function testDelete(): void { $this->assertTrue($this->parentFolder->nodeExists('test')); $this->simpleFolder->delete(); $this->assertFalse($this->parentFolder->nodeExists('test')); } - public function testFileExists() { + public function testFileExists(): void { $this->folder->newFile('exists'); $this->assertFalse($this->simpleFolder->fileExists('not-exists')); $this->assertTrue($this->simpleFolder->fileExists('exists')); } - public function testGetFile() { + public function testGetFile(): void { $this->folder->newFile('exists'); $result = $this->simpleFolder->getFile('exists'); @@ -74,7 +75,7 @@ class SimpleFolderTest extends \Test\TestCase { $this->simpleFolder->getFile('not-exists'); } - public function testNewFile() { + public function testNewFile(): void { $result = $this->simpleFolder->newFile('file'); $this->assertInstanceOf(ISimpleFile::class, $result); $this->assertFalse($this->folder->nodeExists('file')); @@ -84,7 +85,7 @@ class SimpleFolderTest extends \Test\TestCase { $this->assertEquals('bar', $result->getContent()); } - public function testGetDirectoryListing() { + public function testGetDirectoryListing(): void { $this->folder->newFile('file1'); $this->folder->newFile('file2'); @@ -94,7 +95,7 @@ class SimpleFolderTest extends \Test\TestCase { $this->assertInstanceOf(ISimpleFile::class, $result[1]); } - public function testGetFolder() { + public function testGetFolder(): void { $this->folder->newFolder('exists'); $result = $this->simpleFolder->getFolder('exists'); @@ -104,7 +105,7 @@ class SimpleFolderTest extends \Test\TestCase { $this->simpleFolder->getFolder('not-exists'); } - public function testNewFolder() { + public function testNewFolder(): void { $result = $this->simpleFolder->newFolder('folder'); $this->assertInstanceOf(ISimpleFolder::class, $result); $result->newFile('file'); diff --git a/tests/lib/Files/Storage/CommonTest.php b/tests/lib/Files/Storage/CommonTest.php index bd22d93fb69..c5ff6bb0b5f 100644 --- a/tests/lib/Files/Storage/CommonTest.php +++ b/tests/lib/Files/Storage/CommonTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -9,7 +10,12 @@ namespace Test\Files\Storage; use OC\Files\Storage\Wrapper\Jail; use OC\Files\Storage\Wrapper\Wrapper; +use OCP\Files; +use OCP\Files\IFilenameValidator; +use OCP\Files\InvalidCharacterInPathException; use OCP\Files\InvalidPathException; +use OCP\ITempManager; +use OCP\Server; use PHPUnit\Framework\MockObject\MockObject; /** @@ -20,68 +26,46 @@ use PHPUnit\Framework\MockObject\MockObject; * @package Test\Files\Storage */ class CommonTest extends Storage { - /** - * @var string tmpDir - */ - private $tmpDir; - private array $invalidCharsBackup; + private string $tmpDir; + private IFilenameValidator&MockObject $filenameValidator; protected function setUp(): void { parent::setUp(); - $this->tmpDir = \OC::$server->getTempManager()->getTemporaryFolder(); + $this->filenameValidator = $this->createMock(IFilenameValidator::class); + $this->overwriteService(IFilenameValidator::class, $this->filenameValidator); + $this->tmpDir = Server::get(ITempManager::class)->getTemporaryFolder(); $this->instance = new \OC\Files\Storage\CommonTest(['datadir' => $this->tmpDir]); - $this->invalidCharsBackup = \OC::$server->getConfig()->getSystemValue('forbidden_chars', []); } protected function tearDown(): void { - \OC_Helper::rmdirr($this->tmpDir); - \OC::$server->getConfig()->setSystemValue('forbidden_chars', $this->invalidCharsBackup); + Files::rmdirr($this->tmpDir); + $this->restoreService(IFilenameValidator::class); parent::tearDown(); } - /** - * @dataProvider dataVerifyPath - */ - public function testVerifyPath(string $filename, array $additionalChars, bool $throws) { - /** @var \OC\Files\Storage\CommonTest|MockObject $instance */ - $instance = $this->getMockBuilder(\OC\Files\Storage\CommonTest::class) - ->onlyMethods(['copyFromStorage', 'rmdir', 'unlink']) - ->setConstructorArgs([['datadir' => $this->tmpDir]]) - ->getMock(); - $instance->method('copyFromStorage') - ->willThrowException(new \Exception('copy')); - - \OC::$server->getConfig()->setSystemValue('forbidden_chars', $additionalChars); + public function testVerifyPath(): void { + $this->filenameValidator + ->expects($this->once()) + ->method('validateFilename') + ->with('invalid:char.txt') + ->willThrowException(new InvalidCharacterInPathException()); + $this->expectException(InvalidPathException::class); - if ($throws) { - $this->expectException(InvalidPathException::class); - } else { - $this->expectNotToPerformAssertions(); - } - $instance->verifyPath('/', $filename); + $this->instance->verifyPath('/', 'invalid:char.txt'); } - public function dataVerifyPath(): array { - return [ - // slash is always forbidden - 'invalid slash' => ['a/b.txt', [], true], - // backslash is also forbidden - 'invalid backslash' => ['a\\b.txt', [], true], - // by default colon is not forbidden - 'valid name' => ['a: b.txt', [], false], - // colon can be added to the list of forbidden character - 'invalid custom character' => ['a: b.txt', [':'], true], - // make sure to not split the list entries as they migh contain Unicode sequences - // in this example the "face in clouds" emoji contains the clouds emoji so only having clouds is ok - 'valid unicode sequence' => ['🌫️.txt', ['😶🌫️'], false], - // This is the reverse: clouds are forbidden -> so is also the face in the clouds emoji - 'valid unicode sequence' => ['😶🌫️.txt', ['🌫️'], true], - ]; + public function testVerifyPathSucceed(): void { + $this->filenameValidator + ->expects($this->once()) + ->method('validateFilename') + ->with('valid-char.txt'); + + $this->instance->verifyPath('/', 'valid-char.txt'); } - public function testMoveFromStorageWrapped() { + public function testMoveFromStorageWrapped(): void { /** @var \OC\Files\Storage\CommonTest|MockObject $instance */ $instance = $this->getMockBuilder(\OC\Files\Storage\CommonTest::class) ->onlyMethods(['copyFromStorage', 'rmdir', 'unlink']) @@ -99,7 +83,7 @@ class CommonTest extends Storage { $this->assertTrue($instance->file_exists('bar.txt')); } - public function testMoveFromStorageJailed() { + public function testMoveFromStorageJailed(): void { /** @var \OC\Files\Storage\CommonTest|MockObject $instance */ $instance = $this->getMockBuilder(\OC\Files\Storage\CommonTest::class) ->onlyMethods(['copyFromStorage', 'rmdir', 'unlink']) @@ -122,7 +106,7 @@ class CommonTest extends Storage { $this->assertTrue($instance->file_exists('bar.txt')); } - public function testMoveFromStorageNestedJail() { + public function testMoveFromStorageNestedJail(): void { /** @var \OC\Files\Storage\CommonTest|MockObject $instance */ $instance = $this->getMockBuilder(\OC\Files\Storage\CommonTest::class) ->onlyMethods(['copyFromStorage', 'rmdir', 'unlink']) diff --git a/tests/lib/Files/Storage/CopyDirectoryTest.php b/tests/lib/Files/Storage/CopyDirectoryTest.php index 6133361c626..b593b7c984f 100644 --- a/tests/lib/Files/Storage/CopyDirectoryTest.php +++ b/tests/lib/Files/Storage/CopyDirectoryTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,19 +8,20 @@ namespace Test\Files\Storage; +use OC\Files\Storage\PolyFill\CopyDirectory; use OC\Files\Storage\Temporary; class StorageNoRecursiveCopy extends Temporary { - public function copy($path1, $path2) { - if ($this->is_dir($path1)) { + public function copy(string $source, string $target): bool { + if ($this->is_dir($source)) { return false; } - return copy($this->getSourcePath($path1), $this->getSourcePath($path2)); + return copy($this->getSourcePath($source), $this->getSourcePath($target)); } } class CopyDirectoryStorage extends StorageNoRecursiveCopy { - use \OC\Files\Storage\PolyFill\CopyDirectory; + use CopyDirectory; } /** diff --git a/tests/lib/Files/Storage/HomeTest.php b/tests/lib/Files/Storage/HomeTest.php index c3111e74259..84a9816cb0c 100644 --- a/tests/lib/Files/Storage/HomeTest.php +++ b/tests/lib/Files/Storage/HomeTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,20 +8,21 @@ namespace Test\Files\Storage; +use OC\Files\Storage\Home; use OC\User\User; +use OCP\Files; +use OCP\ITempManager; +use OCP\Server; class DummyUser extends User { - private $home; - - private $uid; - /** * @param string $uid * @param string $home */ - public function __construct($uid, $home) { - $this->uid = $uid; - $this->home = $home; + public function __construct( + private $uid, + private $home, + ) { } public function getHome() { @@ -48,39 +50,39 @@ class HomeTest extends Storage { private $userId; /** - * @var \OC\User\User $user + * @var User $user */ private $user; protected function setUp(): void { parent::setUp(); - $this->tmpDir = \OC::$server->getTempManager()->getTemporaryFolder(); + $this->tmpDir = Server::get(ITempManager::class)->getTemporaryFolder(); $this->userId = $this->getUniqueID('user_'); $this->user = new DummyUser($this->userId, $this->tmpDir); - $this->instance = new \OC\Files\Storage\Home(['user' => $this->user]); + $this->instance = new Home(['user' => $this->user]); } protected function tearDown(): void { - \OC_Helper::rmdirr($this->tmpDir); + Files::rmdirr($this->tmpDir); parent::tearDown(); } /** * Tests that the home id is in the format home::user1 */ - public function testId() { + public function testId(): void { $this->assertEquals('home::' . $this->userId, $this->instance->getId()); } /** * Tests that getCache() returns an instance of HomeCache */ - public function testGetCacheReturnsHomeCache() { + public function testGetCacheReturnsHomeCache(): void { $this->assertInstanceOf('\OC\Files\Cache\HomeCache', $this->instance->getCache()); } - public function testGetOwner() { + public function testGetOwner(): void { $this->assertEquals($this->userId, $this->instance->getOwner('')); } } diff --git a/tests/lib/Files/Storage/LocalTest.php b/tests/lib/Files/Storage/LocalTest.php index efe5dd04e47..89449a51351 100644 --- a/tests/lib/Files/Storage/LocalTest.php +++ b/tests/lib/Files/Storage/LocalTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,6 +8,14 @@ namespace Test\Files\Storage; +use OC\Files\Storage\Local; +use OC\Files\Storage\Wrapper\Jail; +use OCP\Files; +use OCP\Files\ForbiddenException; +use OCP\Files\StorageNotAvailableException; +use OCP\ITempManager; +use OCP\Server; + /** * Class LocalTest * @@ -23,23 +32,23 @@ class LocalTest extends Storage { protected function setUp(): void { parent::setUp(); - $this->tmpDir = \OC::$server->getTempManager()->getTemporaryFolder(); - $this->instance = new \OC\Files\Storage\Local(['datadir' => $this->tmpDir]); + $this->tmpDir = Server::get(ITempManager::class)->getTemporaryFolder(); + $this->instance = new Local(['datadir' => $this->tmpDir]); } protected function tearDown(): void { - \OC_Helper::rmdirr($this->tmpDir); + Files::rmdirr($this->tmpDir); parent::tearDown(); } - public function testStableEtag() { + public function testStableEtag(): void { $this->instance->file_put_contents('test.txt', 'foobar'); $etag1 = $this->instance->getETag('test.txt'); $etag2 = $this->instance->getETag('test.txt'); $this->assertEquals($etag1, $etag2); } - public function testEtagChange() { + public function testEtagChange(): void { $this->instance->file_put_contents('test.txt', 'foo'); $this->instance->touch('test.txt', time() - 2); $etag1 = $this->instance->getETag('test.txt'); @@ -49,22 +58,22 @@ class LocalTest extends Storage { } - public function testInvalidArgumentsEmptyArray() { + public function testInvalidArgumentsEmptyArray(): void { $this->expectException(\InvalidArgumentException::class); - new \OC\Files\Storage\Local([]); + new Local([]); } - public function testInvalidArgumentsNoArray() { + public function testInvalidArgumentsNoArray(): void { $this->expectException(\InvalidArgumentException::class); - new \OC\Files\Storage\Local(null); + new Local([]); } - public function testDisallowSymlinksOutsideDatadir() { - $this->expectException(\OCP\Files\ForbiddenException::class); + public function testDisallowSymlinksOutsideDatadir(): void { + $this->expectException(ForbiddenException::class); $subDir1 = $this->tmpDir . 'sub1'; $subDir2 = $this->tmpDir . 'sub2'; @@ -74,12 +83,12 @@ class LocalTest extends Storage { symlink($subDir2, $sym); - $storage = new \OC\Files\Storage\Local(['datadir' => $subDir1]); + $storage = new Local(['datadir' => $subDir1]); $storage->file_put_contents('sym/foo', 'bar'); } - public function testDisallowSymlinksInsideDatadir() { + public function testDisallowSymlinksInsideDatadir(): void { $subDir1 = $this->tmpDir . 'sub1'; $subDir2 = $this->tmpDir . 'sub1/sub2'; $sym = $this->tmpDir . 'sub1/sym'; @@ -88,27 +97,27 @@ class LocalTest extends Storage { symlink($subDir2, $sym); - $storage = new \OC\Files\Storage\Local(['datadir' => $subDir1]); + $storage = new Local(['datadir' => $subDir1]); $storage->file_put_contents('sym/foo', 'bar'); $this->addToAssertionCount(1); } - public function testWriteUmaskFilePutContents() { + public function testWriteUmaskFilePutContents(): void { $oldMask = umask(0333); $this->instance->file_put_contents('test.txt', 'sad'); umask($oldMask); $this->assertTrue($this->instance->isUpdatable('test.txt')); } - public function testWriteUmaskMkdir() { + public function testWriteUmaskMkdir(): void { $oldMask = umask(0333); $this->instance->mkdir('test.txt'); umask($oldMask); $this->assertTrue($this->instance->isUpdatable('test.txt')); } - public function testWriteUmaskFopen() { + public function testWriteUmaskFopen(): void { $oldMask = umask(0333); $handle = $this->instance->fopen('test.txt', 'w'); fwrite($handle, 'foo'); @@ -117,7 +126,7 @@ class LocalTest extends Storage { $this->assertTrue($this->instance->isUpdatable('test.txt')); } - public function testWriteUmaskCopy() { + public function testWriteUmaskCopy(): void { $this->instance->file_put_contents('source.txt', 'sad'); $oldMask = umask(0333); $this->instance->copy('source.txt', 'test.txt'); @@ -125,14 +134,35 @@ class LocalTest extends Storage { $this->assertTrue($this->instance->isUpdatable('test.txt')); } - public function testUnavailableExternal() { - $this->expectException(\OCP\Files\StorageNotAvailableException::class); - $this->instance = new \OC\Files\Storage\Local(['datadir' => $this->tmpDir . '/unexist', 'isExternal' => true]); + public function testUnavailableExternal(): void { + $this->expectException(StorageNotAvailableException::class); + $this->instance = new Local(['datadir' => $this->tmpDir . '/unexist', 'isExternal' => true]); } - public function testUnavailableNonExternal() { - $this->instance = new \OC\Files\Storage\Local(['datadir' => $this->tmpDir . '/unexist']); + public function testUnavailableNonExternal(): void { + $this->instance = new Local(['datadir' => $this->tmpDir . '/unexist']); // no exception thrown $this->assertNotNull($this->instance); } + + public function testMoveNestedJail(): void { + $this->instance->mkdir('foo'); + $this->instance->mkdir('foo/bar'); + $this->instance->mkdir('target'); + $this->instance->file_put_contents('foo/bar/file.txt', 'foo'); + $jail1 = new Jail([ + 'storage' => $this->instance, + 'root' => 'foo' + ]); + $jail2 = new Jail([ + 'storage' => $jail1, + 'root' => 'bar' + ]); + $jail3 = new Jail([ + 'storage' => $this->instance, + 'root' => 'target' + ]); + $jail3->moveFromStorage($jail2, 'file.txt', 'file.txt'); + $this->assertTrue($this->instance->file_exists('target/file.txt')); + } } diff --git a/tests/lib/Files/Storage/Storage.php b/tests/lib/Files/Storage/Storage.php index 0a170a0e7d5..51bb5b7c8ad 100644 --- a/tests/lib/Files/Storage/Storage.php +++ b/tests/lib/Files/Storage/Storage.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -8,6 +9,8 @@ namespace Test\Files\Storage; use OC\Files\Cache\Watcher; +use OC\Files\Storage\Wrapper\Wrapper; +use OCP\Files\Storage\IStorage; use OCP\Files\Storage\IWriteStreamStorage; abstract class Storage extends \Test\TestCase { @@ -30,7 +33,7 @@ abstract class Storage extends \Test\TestCase { /** * the root folder of the storage should always exist, be readable and be recognized as a directory */ - public function testRoot() { + public function testRoot(): void { $this->assertTrue($this->instance->file_exists('/'), 'Root folder does not exist'); $this->assertTrue($this->instance->isReadable('/'), 'Root folder is not readable'); $this->assertTrue($this->instance->is_dir('/'), 'Root folder is not a directory'); @@ -44,14 +47,12 @@ abstract class Storage extends \Test\TestCase { /** * Check that the test() function works */ - public function testTestFunction() { + public function testTestFunction(): void { $this->assertTrue($this->instance->test()); } - /** - * @dataProvider directoryProvider - */ - public function testDirectories($directory) { + #[\PHPUnit\Framework\Attributes\DataProvider('directoryProvider')] + public function testDirectories($directory): void { $this->assertFalse($this->instance->file_exists('/' . $directory)); $this->assertTrue($this->instance->mkdir('/' . $directory)); @@ -66,7 +67,7 @@ abstract class Storage extends \Test\TestCase { $dh = $this->instance->opendir('/'); $content = []; - while ($file = readdir($dh)) { + while (($file = readdir($dh)) !== false) { if ($file != '.' and $file != '..') { $content[] = $file; } @@ -99,7 +100,7 @@ abstract class Storage extends \Test\TestCase { $dh = $this->instance->opendir('/'); $content = []; - while ($file = readdir($dh)) { + while (($file = readdir($dh)) !== false) { if ($file != '.' and $file != '..') { $content[] = $file; } @@ -107,7 +108,7 @@ abstract class Storage extends \Test\TestCase { $this->assertEquals([], $content); } - public function fileNameProvider() { + public static function fileNameProvider(): array { return [ ['file.txt'], [' file.txt'], @@ -118,7 +119,7 @@ abstract class Storage extends \Test\TestCase { ]; } - public function directoryProvider() { + public static function directoryProvider(): array { return [ ['folder'], [' folder'], @@ -129,7 +130,7 @@ abstract class Storage extends \Test\TestCase { ]; } - public function loremFileProvider() { + public static function loremFileProvider(): array { $root = \OC::$SERVERROOT . '/tests/data/'; return [ // small file @@ -141,10 +142,9 @@ abstract class Storage extends \Test\TestCase { /** * test the various uses of file_get_contents and file_put_contents - * - * @dataProvider loremFileProvider */ - public function testGetPutContents($sourceFile) { + #[\PHPUnit\Framework\Attributes\DataProvider('loremFileProvider')] + public function testGetPutContents($sourceFile): void { $sourceText = file_get_contents($sourceFile); //fill a file with string data @@ -160,7 +160,7 @@ abstract class Storage extends \Test\TestCase { /** * test various known mimetypes */ - public function testMimeType() { + public function testMimeType(): void { $this->assertEquals('httpd/unix-directory', $this->instance->getMimeType('/')); $this->assertEquals(false, $this->instance->getMimeType('/non/existing/file')); @@ -178,7 +178,7 @@ abstract class Storage extends \Test\TestCase { } - public function copyAndMoveProvider() { + public static function copyAndMoveProvider(): array { return [ ['/source.txt', '/target.txt'], ['/source.txt', '/target with space.txt'], @@ -209,10 +209,8 @@ abstract class Storage extends \Test\TestCase { ); } - /** - * @dataProvider copyAndMoveProvider - */ - public function testCopy($source, $target) { + #[\PHPUnit\Framework\Attributes\DataProvider('copyAndMoveProvider')] + public function testCopy($source, $target): void { $this->initSourceAndTarget($source); $this->instance->copy($source, $target); @@ -222,10 +220,8 @@ abstract class Storage extends \Test\TestCase { $this->assertTrue($this->instance->file_exists($source), $source . ' was deleted'); } - /** - * @dataProvider copyAndMoveProvider - */ - public function testMove($source, $target) { + #[\PHPUnit\Framework\Attributes\DataProvider('copyAndMoveProvider')] + public function testMove($source, $target): void { $this->initSourceAndTarget($source); $this->instance->rename($source, $target); @@ -236,10 +232,8 @@ abstract class Storage extends \Test\TestCase { $this->assertSameAsLorem($target); } - /** - * @dataProvider copyAndMoveProvider - */ - public function testCopyOverwrite($source, $target) { + #[\PHPUnit\Framework\Attributes\DataProvider('copyAndMoveProvider')] + public function testCopyOverwrite($source, $target): void { $this->initSourceAndTarget($source, $target); $this->instance->copy($source, $target); @@ -250,10 +244,8 @@ abstract class Storage extends \Test\TestCase { $this->assertSameAsLorem($source); } - /** - * @dataProvider copyAndMoveProvider - */ - public function testMoveOverwrite($source, $target) { + #[\PHPUnit\Framework\Attributes\DataProvider('copyAndMoveProvider')] + public function testMoveOverwrite($source, $target): void { $this->initSourceAndTarget($source, $target); $this->instance->rename($source, $target); @@ -263,7 +255,7 @@ abstract class Storage extends \Test\TestCase { $this->assertSameAsLorem($target); } - public function testLocal() { + public function testLocal(): void { $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; $this->instance->file_put_contents('/lorem.txt', file_get_contents($textFile)); $localFile = $this->instance->getLocalFile('/lorem.txt'); @@ -290,7 +282,7 @@ abstract class Storage extends \Test\TestCase { $this->assertEquals(file_get_contents($localFile), 'foo'); } - public function testStat() { + public function testStat(): void { $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; $ctimeStart = time(); $this->instance->file_put_contents('/lorem.txt', file_get_contents($textFile)); @@ -325,8 +317,8 @@ abstract class Storage extends \Test\TestCase { * Test whether checkUpdate properly returns false when there was * no change. */ - public function testCheckUpdate() { - if ($this->instance instanceof \OC\Files\Storage\Wrapper\Wrapper) { + public function testCheckUpdate(): void { + if ($this->instance instanceof Wrapper) { $this->markTestSkipped('Cannot test update check on wrappers'); } $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; @@ -337,7 +329,7 @@ abstract class Storage extends \Test\TestCase { $this->assertFalse($watcher->checkUpdate('/lorem.txt'), 'No update'); } - public function testUnlink() { + public function testUnlink(): void { $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; $this->instance->file_put_contents('/lorem.txt', file_get_contents($textFile)); @@ -349,10 +341,8 @@ abstract class Storage extends \Test\TestCase { $this->assertFalse($this->instance->file_exists('/lorem.txt')); } - /** - * @dataProvider fileNameProvider - */ - public function testFOpen($fileName) { + #[\PHPUnit\Framework\Attributes\DataProvider('fileNameProvider')] + public function testFOpen($fileName): void { $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; $fh = @$this->instance->fopen($fileName, 'r'); @@ -372,14 +362,14 @@ abstract class Storage extends \Test\TestCase { $this->assertEquals(file_get_contents($textFile), $content); } - public function testTouchCreateFile() { + public function testTouchCreateFile(): void { $this->assertFalse($this->instance->file_exists('touch')); // returns true on success $this->assertTrue($this->instance->touch('touch')); $this->assertTrue($this->instance->file_exists('touch')); } - public function testRecursiveRmdir() { + public function testRecursiveRmdir(): void { $this->instance->mkdir('folder'); $this->instance->mkdir('folder/bar'); $this->wait(); @@ -393,14 +383,14 @@ abstract class Storage extends \Test\TestCase { $this->assertFalse($this->instance->file_exists('folder')); } - public function testRmdirEmptyFolder() { + public function testRmdirEmptyFolder(): void { $this->assertTrue($this->instance->mkdir('empty')); $this->wait(); $this->assertTrue($this->instance->rmdir('empty')); $this->assertFalse($this->instance->file_exists('empty')); } - public function testRecursiveUnlink() { + public function testRecursiveUnlink(): void { $this->instance->mkdir('folder'); $this->instance->mkdir('folder/bar'); $this->instance->file_put_contents('folder/asd.txt', 'foobar'); @@ -413,7 +403,7 @@ abstract class Storage extends \Test\TestCase { $this->assertFalse($this->instance->file_exists('folder')); } - public function hashProvider() { + public static function hashProvider(): array { return [ ['Foobar', 'md5'], ['Foobar', 'sha1'], @@ -421,16 +411,14 @@ abstract class Storage extends \Test\TestCase { ]; } - /** - * @dataProvider hashProvider - */ - public function testHash($data, $type) { + #[\PHPUnit\Framework\Attributes\DataProvider('hashProvider')] + public function testHash($data, $type): void { $this->instance->file_put_contents('hash.txt', $data); $this->assertEquals(hash($type, $data), $this->instance->hash($type, 'hash.txt')); $this->assertEquals(hash($type, $data, true), $this->instance->hash($type, 'hash.txt', true)); } - public function testHashInFileName() { + public function testHashInFileName(): void { $this->instance->file_put_contents('#test.txt', 'data'); $this->assertEquals('data', $this->instance->file_get_contents('#test.txt')); @@ -449,14 +437,14 @@ abstract class Storage extends \Test\TestCase { $this->assertEquals(['test.txt'], $content); } - public function testCopyOverWriteFile() { + public function testCopyOverWriteFile(): void { $this->instance->file_put_contents('target.txt', 'foo'); $this->instance->file_put_contents('source.txt', 'bar'); $this->instance->copy('source.txt', 'target.txt'); $this->assertEquals('bar', $this->instance->file_get_contents('target.txt')); } - public function testRenameOverWriteFile() { + public function testRenameOverWriteFile(): void { $this->instance->file_put_contents('target.txt', 'foo'); $this->instance->file_put_contents('source.txt', 'bar'); $this->instance->rename('source.txt', 'target.txt'); @@ -464,7 +452,7 @@ abstract class Storage extends \Test\TestCase { $this->assertFalse($this->instance->file_exists('source.txt')); } - public function testRenameDirectory() { + public function testRenameDirectory(): void { $this->instance->mkdir('source'); $this->instance->file_put_contents('source/test1.txt', 'foo'); $this->instance->file_put_contents('source/test2.txt', 'qwerty'); @@ -492,7 +480,7 @@ abstract class Storage extends \Test\TestCase { $this->assertEquals('bar', $this->instance->file_get_contents('target/subfolder/test.txt')); } - public function testRenameOverWriteDirectory() { + public function testRenameOverWriteDirectory(): void { $this->instance->mkdir('source'); $this->instance->file_put_contents('source/test1.txt', 'foo'); @@ -508,7 +496,7 @@ abstract class Storage extends \Test\TestCase { $this->assertEquals('foo', $this->instance->file_get_contents('target/test1.txt'), 'target/test1.txt has not been overwritten'); } - public function testRenameOverWriteDirectoryOverFile() { + public function testRenameOverWriteDirectoryOverFile(): void { $this->instance->mkdir('source'); $this->instance->file_put_contents('source/test1.txt', 'foo'); @@ -521,7 +509,7 @@ abstract class Storage extends \Test\TestCase { $this->assertEquals('foo', $this->instance->file_get_contents('target/test1.txt')); } - public function testCopyDirectory() { + public function testCopyDirectory(): void { $this->instance->mkdir('source'); $this->instance->file_put_contents('source/test1.txt', 'foo'); $this->instance->file_put_contents('source/test2.txt', 'qwerty'); @@ -546,7 +534,7 @@ abstract class Storage extends \Test\TestCase { $this->assertEquals('bar', $this->instance->file_get_contents('target/subfolder/test.txt')); } - public function testCopyOverWriteDirectory() { + public function testCopyOverWriteDirectory(): void { $this->instance->mkdir('source'); $this->instance->file_put_contents('source/test1.txt', 'foo'); @@ -556,11 +544,11 @@ abstract class Storage extends \Test\TestCase { $this->instance->copy('source', 'target'); - $this->assertFalse($this->instance->file_exists('target/test2.txt')); + $this->assertFalse($this->instance->file_exists('target/test2.txt'), 'File target/test2.txt should no longer exist, but does'); $this->assertEquals('foo', $this->instance->file_get_contents('target/test1.txt')); } - public function testCopyOverWriteDirectoryOverFile() { + public function testCopyOverWriteDirectoryOverFile(): void { $this->instance->mkdir('source'); $this->instance->file_put_contents('source/test1.txt', 'foo'); @@ -571,16 +559,14 @@ abstract class Storage extends \Test\TestCase { $this->assertEquals('foo', $this->instance->file_get_contents('target/test1.txt')); } - public function testInstanceOfStorage() { - $this->assertTrue($this->instance->instanceOfStorage('\OCP\Files\Storage')); + public function testInstanceOfStorage(): void { + $this->assertTrue($this->instance->instanceOfStorage(IStorage::class)); $this->assertTrue($this->instance->instanceOfStorage(get_class($this->instance))); $this->assertFalse($this->instance->instanceOfStorage('\OC')); } - /** - * @dataProvider copyAndMoveProvider - */ - public function testCopyFromSameStorage($source, $target) { + #[\PHPUnit\Framework\Attributes\DataProvider('copyAndMoveProvider')] + public function testCopyFromSameStorage($source, $target): void { $this->initSourceAndTarget($source); $this->instance->copyFromStorage($this->instance, $source, $target); @@ -590,32 +576,32 @@ abstract class Storage extends \Test\TestCase { $this->assertTrue($this->instance->file_exists($source), $source . ' was deleted'); } - public function testIsCreatable() { + public function testIsCreatable(): void { $this->instance->mkdir('source'); $this->assertTrue($this->instance->isCreatable('source')); } - public function testIsReadable() { + public function testIsReadable(): void { $this->instance->mkdir('source'); $this->assertTrue($this->instance->isReadable('source')); } - public function testIsUpdatable() { + public function testIsUpdatable(): void { $this->instance->mkdir('source'); $this->assertTrue($this->instance->isUpdatable('source')); } - public function testIsDeletable() { + public function testIsDeletable(): void { $this->instance->mkdir('source'); $this->assertTrue($this->instance->isDeletable('source')); } - public function testIsShareable() { + public function testIsShareable(): void { $this->instance->mkdir('source'); $this->assertTrue($this->instance->isSharable('source')); } - public function testStatAfterWrite() { + public function testStatAfterWrite(): void { $this->instance->file_put_contents('foo.txt', 'bar'); $stat = $this->instance->stat('foo.txt'); $this->assertEquals(3, $stat['size']); @@ -628,13 +614,13 @@ abstract class Storage extends \Test\TestCase { $this->assertEquals(6, $stat['size']); } - public function testPartFile() { + public function testPartFile(): void { $this->instance->file_put_contents('bar.txt.part', 'bar'); $this->instance->rename('bar.txt.part', 'bar.txt'); $this->assertEquals('bar', $this->instance->file_get_contents('bar.txt')); } - public function testWriteStream() { + public function testWriteStream(): void { $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; if (!$this->instance->instanceOfStorage(IWriteStreamStorage::class)) { @@ -651,7 +637,7 @@ abstract class Storage extends \Test\TestCase { $this->assertEquals('resource (closed)', gettype($source)); } - public function testFseekSize() { + public function testFseekSize(): void { $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; $this->instance->file_put_contents('bar.txt', file_get_contents($textFile)); diff --git a/tests/lib/Files/Storage/StorageFactoryTest.php b/tests/lib/Files/Storage/StorageFactoryTest.php index ee23f6199c9..0bb9cbf5824 100644 --- a/tests/lib/Files/Storage/StorageFactoryTest.php +++ b/tests/lib/Files/Storage/StorageFactoryTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -8,25 +9,26 @@ namespace Test\Files\Storage; use OC\Files\Mount\MountPoint; +use OC\Files\Storage\StorageFactory; use OC\Files\Storage\Wrapper\Wrapper; use OCP\Files\Mount\IMountPoint; -use OCP\Files\Storage as IStorage; +use OCP\Files\Storage\IStorage; use Test\TestCase; class DummyWrapper extends Wrapper { public $data; - public function __construct($arguments) { - parent::__construct($arguments); - if (isset($arguments['data'])) { - $this->data = $arguments['data']; + public function __construct(array $parameters) { + parent::__construct($parameters); + if (isset($parameters['data'])) { + $this->data = $parameters['data']; } } } class StorageFactoryTest extends TestCase { - public function testSimpleWrapper() { - $instance = new \OC\Files\Storage\StorageFactory(); + public function testSimpleWrapper(): void { + $instance = new StorageFactory(); $mount = new MountPoint('\OC\Files\Storage\Temporary', '/foo', [[]], $instance); $instance->addStorageWrapper('dummy', function ($mountPoint, IStorage $storage, IMountPoint $mount) { $this->assertInstanceOf('\OC\Files\Storage\Temporary', $storage); @@ -38,8 +40,8 @@ class StorageFactoryTest extends TestCase { $this->assertInstanceOf('\Test\Files\Storage\DummyWrapper', $wrapped); } - public function testRemoveWrapper() { - $instance = new \OC\Files\Storage\StorageFactory(); + public function testRemoveWrapper(): void { + $instance = new StorageFactory(); $mount = new MountPoint('\OC\Files\Storage\Temporary', '/foo', [[]], $instance); $instance->addStorageWrapper('dummy', function ($mountPoint, IStorage $storage) { return new DummyWrapper(['storage' => $storage]); @@ -49,8 +51,8 @@ class StorageFactoryTest extends TestCase { $this->assertInstanceOf('\OC\Files\Storage\Temporary', $wrapped); } - public function testWrapperPriority() { - $instance = new \OC\Files\Storage\StorageFactory(); + public function testWrapperPriority(): void { + $instance = new StorageFactory(); $mount = new MountPoint('\OC\Files\Storage\Temporary', '/foo', [[]], $instance); $instance->addStorageWrapper('dummy1', function ($mountPoint, IStorage $storage) { return new DummyWrapper(['storage' => $storage, 'data' => 1]); diff --git a/tests/lib/Files/Storage/StoragesTestCase.php b/tests/lib/Files/Storage/StoragesTestCase.php new file mode 100644 index 00000000000..565ff1ddfda --- /dev/null +++ b/tests/lib/Files/Storage/StoragesTestCase.php @@ -0,0 +1,128 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace Test\Files\Storage; + +use OC\Files\Storage\Storage; +use Test\TestCase; + +abstract class StoragesTestCase extends TestCase { + /** + * @var Storage + */ + protected $storage1; + + /** + * @var Storage + */ + protected $storage2; + + protected function tearDown(): void { + if (is_null($this->storage1) && is_null($this->storage2)) { + return; + } + $this->storage1->getCache()->clear(); + $this->storage2->getCache()->clear(); + + parent::tearDown(); + } + + public function testMoveFileFromStorage() { + $source = 'source.txt'; + $target = 'target.txt'; + $this->storage2->file_put_contents($source, 'foo'); + + $this->storage1->moveFromStorage($this->storage2, $source, $target); + + $this->assertTrue($this->storage1->file_exists($target), $target . ' was not created'); + $this->assertFalse($this->storage2->file_exists($source), $source . ' still exists'); + $this->assertEquals('foo', $this->storage1->file_get_contents($target)); + } + + public function testMoveFileFromStorageWithExistingTarget() { + $source = 'source.txt'; + $target = 'target.txt'; + $this->storage1->file_put_contents($target, 'bar'); + $this->storage2->file_put_contents($source, 'foo'); + + $targetURN = $this->storage1->getURN($this->storage1->getCache()->get($target)->getID()); + $sourceURN = $this->storage2->getURN($this->storage2->getCache()->get($source)->getID()); + + $this->storage1->moveFromStorage($this->storage2, $source, $target); + + $this->assertTrue($this->storage1->file_exists($target), $target . ' was not created in DB'); + $this->assertFalse($this->storage2->file_exists($source), $source . ' still exists in DB'); + $this->assertTrue($this->storage1->getObjectStore()->objectExists($sourceURN), $sourceURN . ' was not created in bucket'); + $this->assertFalse($this->storage1->getObjectStore()->objectExists($targetURN), $targetURN . ' still exists in bucket'); + $this->assertEquals('foo', $this->storage1->file_get_contents($target)); + } + + public function testMoveDirectoryFromStorage() { + $this->storage2->mkdir('source'); + $this->storage2->file_put_contents('source/test1.txt', 'foo'); + $this->storage2->file_put_contents('source/test2.txt', 'qwerty'); + $this->storage2->mkdir('source/subfolder'); + $this->storage2->file_put_contents('source/subfolder/test.txt', 'bar'); + + $this->storage1->moveFromStorage($this->storage2, 'source', 'target'); + + $this->assertTrue($this->storage1->file_exists('target')); + $this->assertTrue($this->storage1->file_exists('target/test1.txt')); + $this->assertTrue($this->storage1->file_exists('target/test2.txt')); + $this->assertTrue($this->storage1->file_exists('target/subfolder')); + $this->assertTrue($this->storage1->file_exists('target/subfolder/test.txt')); + + $this->assertFalse($this->storage2->file_exists('source')); + $this->assertFalse($this->storage2->file_exists('source/test1.txt')); + $this->assertFalse($this->storage2->file_exists('source/test2.txt')); + $this->assertFalse($this->storage2->file_exists('source/subfolder')); + $this->assertFalse($this->storage2->file_exists('source/subfolder/test.txt')); + + $this->assertEquals('foo', $this->storage1->file_get_contents('target/test1.txt')); + $this->assertEquals('qwerty', $this->storage1->file_get_contents('target/test2.txt')); + $this->assertEquals('bar', $this->storage1->file_get_contents('target/subfolder/test.txt')); + } + + public function testCopyFileFromStorage() { + $source = 'source.txt'; + $target = 'target.txt'; + $this->storage2->file_put_contents($source, 'foo'); + + $this->storage1->copyFromStorage($this->storage2, $source, $target); + + $this->assertTrue($this->storage1->file_exists($target), $target . ' was not created'); + $this->assertTrue($this->storage2->file_exists($source), $source . ' was deleted'); + $this->assertEquals('foo', $this->storage1->file_get_contents($target)); + } + + public function testCopyDirectoryFromStorage() { + $this->storage2->mkdir('source'); + $this->storage2->file_put_contents('source/test1.txt', 'foo'); + $this->storage2->file_put_contents('source/test2.txt', 'qwerty'); + $this->storage2->mkdir('source/subfolder'); + $this->storage2->file_put_contents('source/subfolder/test.txt', 'bar'); + + $this->storage1->copyFromStorage($this->storage2, 'source', 'target'); + + $this->assertTrue($this->storage1->file_exists('target')); + $this->assertTrue($this->storage1->file_exists('target/test1.txt')); + $this->assertTrue($this->storage1->file_exists('target/test2.txt')); + $this->assertTrue($this->storage1->file_exists('target/subfolder')); + $this->assertTrue($this->storage1->file_exists('target/subfolder/test.txt')); + + $this->assertTrue($this->storage2->file_exists('source')); + $this->assertTrue($this->storage2->file_exists('source/test1.txt')); + $this->assertTrue($this->storage2->file_exists('source/test2.txt')); + $this->assertTrue($this->storage2->file_exists('source/subfolder')); + $this->assertTrue($this->storage2->file_exists('source/subfolder/test.txt')); + + $this->assertEquals('foo', $this->storage1->file_get_contents('target/test1.txt')); + $this->assertEquals('qwerty', $this->storage1->file_get_contents('target/test2.txt')); + $this->assertEquals('bar', $this->storage1->file_get_contents('target/subfolder/test.txt')); + } +} diff --git a/tests/lib/Files/Storage/Wrapper/AvailabilityTest.php b/tests/lib/Files/Storage/Wrapper/AvailabilityTest.php index ef7b457636c..d890081cbb6 100644 --- a/tests/lib/Files/Storage/Wrapper/AvailabilityTest.php +++ b/tests/lib/Files/Storage/Wrapper/AvailabilityTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -17,7 +18,7 @@ class AvailabilityTest extends \Test\TestCase { protected $storageCache; /** @var \PHPUnit\Framework\MockObject\MockObject|Temporary */ protected $storage; - /** @var Availability */ + /** @var Availability */ protected $wrapper; protected function setUp(): void { @@ -36,7 +37,7 @@ class AvailabilityTest extends \Test\TestCase { /** * Storage is available */ - public function testAvailable() { + public function testAvailable(): void { $this->storage->expects($this->once()) ->method('getAvailability') ->willReturn(['available' => true, 'last_checked' => 0]); @@ -52,8 +53,8 @@ class AvailabilityTest extends \Test\TestCase { * Storage marked unavailable, TTL not expired * */ - public function testUnavailable() { - $this->expectException(\OCP\Files\StorageNotAvailableException::class); + public function testUnavailable(): void { + $this->expectException(StorageNotAvailableException::class); $this->storage->expects($this->once()) ->method('getAvailability') @@ -69,19 +70,23 @@ class AvailabilityTest extends \Test\TestCase { /** * Storage marked unavailable, TTL expired */ - public function testUnavailableRecheck() { + public function testUnavailableRecheck(): void { $this->storage->expects($this->once()) ->method('getAvailability') ->willReturn(['available' => false, 'last_checked' => 0]); $this->storage->expects($this->once()) ->method('test') ->willReturn(true); + $calls = [ + false, // prevents concurrent rechecks + true, // sets correct availability + ]; $this->storage->expects($this->exactly(2)) ->method('setAvailability') - ->withConsecutive( - [$this->equalTo(false)], // prevents concurrent rechecks - [$this->equalTo(true)] // sets correct availability - ); + ->willReturnCallback(function ($value) use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, $value); + }); $this->storage->expects($this->once()) ->method('mkdir'); @@ -92,8 +97,8 @@ class AvailabilityTest extends \Test\TestCase { * Storage marked available, but throws StorageNotAvailableException * */ - public function testAvailableThrowStorageNotAvailable() { - $this->expectException(\OCP\Files\StorageNotAvailableException::class); + public function testAvailableThrowStorageNotAvailable(): void { + $this->expectException(StorageNotAvailableException::class); $this->storage->expects($this->once()) ->method('getAvailability') @@ -102,7 +107,7 @@ class AvailabilityTest extends \Test\TestCase { ->method('test'); $this->storage->expects($this->once()) ->method('mkdir') - ->will($this->throwException(new StorageNotAvailableException())); + ->willThrowException(new StorageNotAvailableException()); $this->storageCache->expects($this->once()) ->method('setAvailability') ->with($this->equalTo(false)); @@ -114,7 +119,7 @@ class AvailabilityTest extends \Test\TestCase { * Storage available, but call fails * Method failure does not indicate storage unavailability */ - public function testAvailableFailure() { + public function testAvailableFailure(): void { $this->storage->expects($this->once()) ->method('getAvailability') ->willReturn(['available' => true, 'last_checked' => 0]); @@ -134,7 +139,7 @@ class AvailabilityTest extends \Test\TestCase { * Standard exception does not indicate storage unavailability * */ - public function testAvailableThrow() { + public function testAvailableThrow(): void { $this->expectException(\Exception::class); $this->storage->expects($this->once()) @@ -144,7 +149,7 @@ class AvailabilityTest extends \Test\TestCase { ->method('test'); $this->storage->expects($this->once()) ->method('mkdir') - ->will($this->throwException(new \Exception())); + ->willThrowException(new \Exception()); $this->storage->expects($this->never()) ->method('setAvailability'); diff --git a/tests/lib/Files/Storage/Wrapper/EncodingTest.php b/tests/lib/Files/Storage/Wrapper/EncodingTest.php index bc9355d7bfb..cb6b6de0fb7 100644 --- a/tests/lib/Files/Storage/Wrapper/EncodingTest.php +++ b/tests/lib/Files/Storage/Wrapper/EncodingTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,19 +8,22 @@ namespace Test\Files\Storage\Wrapper; +use OC\Files\Storage\Temporary; +use OC\Files\Storage\Wrapper\Encoding; + class EncodingTest extends \Test\Files\Storage\Storage { public const NFD_NAME = 'ümlaut'; public const NFC_NAME = 'ümlaut'; /** - * @var \OC\Files\Storage\Temporary + * @var Temporary */ private $sourceStorage; protected function setUp(): void { parent::setUp(); - $this->sourceStorage = new \OC\Files\Storage\Temporary([]); - $this->instance = new \OC\Files\Storage\Wrapper\Encoding([ + $this->sourceStorage = new Temporary([]); + $this->instance = new Encoding([ 'storage' => $this->sourceStorage ]); } @@ -29,43 +33,39 @@ class EncodingTest extends \Test\Files\Storage\Storage { parent::tearDown(); } - public function directoryProvider() { + public static function directoryProvider(): array { $a = parent::directoryProvider(); $a[] = [self::NFC_NAME]; return $a; } - public function fileNameProvider() { + public static function fileNameProvider(): array { $a = parent::fileNameProvider(); $a[] = [self::NFD_NAME . '.txt']; return $a; } - public function copyAndMoveProvider() { + public static function copyAndMoveProvider(): array { $a = parent::copyAndMoveProvider(); $a[] = [self::NFD_NAME . '.txt', self::NFC_NAME . '-renamed.txt']; return $a; } - public function accessNameProvider() { + public static function accessNameProvider(): array { return [ [self::NFD_NAME], [self::NFC_NAME], ]; } - /** - * @dataProvider accessNameProvider - */ - public function testFputEncoding($accessName) { + #[\PHPUnit\Framework\Attributes\DataProvider('accessNameProvider')] + public function testFputEncoding($accessName): void { $this->sourceStorage->file_put_contents(self::NFD_NAME, 'bar'); $this->assertEquals('bar', $this->instance->file_get_contents($accessName)); } - /** - * @dataProvider accessNameProvider - */ - public function testFopenReadEncoding($accessName) { + #[\PHPUnit\Framework\Attributes\DataProvider('accessNameProvider')] + public function testFopenReadEncoding($accessName): void { $this->sourceStorage->file_put_contents(self::NFD_NAME, 'bar'); $fh = $this->instance->fopen($accessName, 'r'); $data = fgets($fh); @@ -73,10 +73,8 @@ class EncodingTest extends \Test\Files\Storage\Storage { $this->assertEquals('bar', $data); } - /** - * @dataProvider accessNameProvider - */ - public function testFopenOverwriteEncoding($accessName) { + #[\PHPUnit\Framework\Attributes\DataProvider('accessNameProvider')] + public function testFopenOverwriteEncoding($accessName): void { $this->sourceStorage->file_put_contents(self::NFD_NAME, 'bar'); $fh = $this->instance->fopen($accessName, 'w'); $data = fputs($fh, 'test'); @@ -86,42 +84,36 @@ class EncodingTest extends \Test\Files\Storage\Storage { $this->assertFalse($this->sourceStorage->file_exists(self::NFC_NAME)); } - /** - * @dataProvider accessNameProvider - */ - public function testFileExistsEncoding($accessName) { + #[\PHPUnit\Framework\Attributes\DataProvider('accessNameProvider')] + public function testFileExistsEncoding($accessName): void { $this->sourceStorage->file_put_contents(self::NFD_NAME, 'bar'); $this->assertTrue($this->instance->file_exists($accessName)); } - /** - * @dataProvider accessNameProvider - */ - public function testUnlinkEncoding($accessName) { + #[\PHPUnit\Framework\Attributes\DataProvider('accessNameProvider')] + public function testUnlinkEncoding($accessName): void { $this->sourceStorage->file_put_contents(self::NFD_NAME, 'bar'); $this->assertTrue($this->instance->unlink($accessName)); $this->assertFalse($this->sourceStorage->file_exists(self::NFC_NAME)); $this->assertFalse($this->sourceStorage->file_exists(self::NFD_NAME)); } - public function testNfcHigherPriority() { + public function testNfcHigherPriority(): void { $this->sourceStorage->file_put_contents(self::NFC_NAME, 'nfc'); $this->sourceStorage->file_put_contents(self::NFD_NAME, 'nfd'); $this->assertEquals('nfc', $this->instance->file_get_contents(self::NFC_NAME)); } - public function encodedDirectoriesProvider() { + public static function encodedDirectoriesProvider(): array { return [ [self::NFD_NAME, self::NFC_NAME], [self::NFD_NAME . '/' . self::NFD_NAME, self::NFC_NAME . '/' . self::NFC_NAME], - [self::NFD_NAME . '/' . self::NFC_NAME . '/' .self::NFD_NAME, self::NFC_NAME . '/' . self::NFC_NAME . '/' . self::NFC_NAME], + [self::NFD_NAME . '/' . self::NFC_NAME . '/' . self::NFD_NAME, self::NFC_NAME . '/' . self::NFC_NAME . '/' . self::NFC_NAME], ]; } - /** - * @dataProvider encodedDirectoriesProvider - */ - public function testOperationInsideDirectory($sourceDir, $accessDir) { + #[\PHPUnit\Framework\Attributes\DataProvider('encodedDirectoriesProvider')] + public function testOperationInsideDirectory($sourceDir, $accessDir): void { $this->sourceStorage->mkdir($sourceDir); $this->instance->file_put_contents($accessDir . '/test.txt', 'bar'); $this->assertTrue($this->instance->file_exists($accessDir . '/test.txt')); @@ -138,7 +130,7 @@ class EncodingTest extends \Test\Files\Storage\Storage { $this->assertTrue($this->instance->file_exists($accessDir . '/' . self::NFC_NAME)); } - public function testCacheExtraSlash() { + public function testCacheExtraSlash(): void { $this->sourceStorage->file_put_contents(self::NFD_NAME, 'foo'); $this->assertEquals(3, $this->instance->file_put_contents(self::NFC_NAME, 'bar')); $this->assertEquals('bar', $this->instance->file_get_contents(self::NFC_NAME)); @@ -150,7 +142,7 @@ class EncodingTest extends \Test\Files\Storage\Storage { $this->assertEquals('barbaric', $this->instance->file_get_contents('//' . self::NFC_NAME)); } - public function sourceAndTargetDirectoryProvider() { + public static function sourceAndTargetDirectoryProvider(): array { return [ [self::NFC_NAME . '1', self::NFC_NAME . '2'], [self::NFD_NAME . '1', self::NFC_NAME . '2'], @@ -159,10 +151,8 @@ class EncodingTest extends \Test\Files\Storage\Storage { ]; } - /** - * @dataProvider sourceAndTargetDirectoryProvider - */ - public function testCopyAndMoveEncodedFolder($sourceDir, $targetDir) { + #[\PHPUnit\Framework\Attributes\DataProvider('sourceAndTargetDirectoryProvider')] + public function testCopyAndMoveEncodedFolder($sourceDir, $targetDir): void { $this->sourceStorage->mkdir($sourceDir); $this->sourceStorage->mkdir($targetDir); $this->sourceStorage->file_put_contents($sourceDir . '/test.txt', 'bar'); @@ -179,10 +169,8 @@ class EncodingTest extends \Test\Files\Storage\Storage { $this->assertEquals('bar', $this->instance->file_get_contents(self::NFC_NAME . '2/test2.txt')); } - /** - * @dataProvider sourceAndTargetDirectoryProvider - */ - public function testCopyAndMoveFromStorageEncodedFolder($sourceDir, $targetDir) { + #[\PHPUnit\Framework\Attributes\DataProvider('sourceAndTargetDirectoryProvider')] + public function testCopyAndMoveFromStorageEncodedFolder($sourceDir, $targetDir): void { $this->sourceStorage->mkdir($sourceDir); $this->sourceStorage->mkdir($targetDir); $this->sourceStorage->file_put_contents($sourceDir . '/test.txt', 'bar'); @@ -199,7 +187,7 @@ class EncodingTest extends \Test\Files\Storage\Storage { $this->assertEquals('bar', $this->instance->file_get_contents(self::NFC_NAME . '2/test2.txt')); } - public function testNormalizedDirectoryEntriesOpenDir() { + public function testNormalizedDirectoryEntriesOpenDir(): void { $this->sourceStorage->mkdir('/test'); $this->sourceStorage->mkdir('/test/' . self::NFD_NAME); @@ -208,7 +196,7 @@ class EncodingTest extends \Test\Files\Storage\Storage { $dh = $this->instance->opendir('/test'); $content = []; - while ($file = readdir($dh)) { + while (($file = readdir($dh)) !== false) { if ($file != '.' and $file != '..') { $content[] = $file; } @@ -218,7 +206,7 @@ class EncodingTest extends \Test\Files\Storage\Storage { $this->assertEquals(self::NFC_NAME, $content[0]); } - public function testNormalizedDirectoryEntriesGetDirectoryContent() { + public function testNormalizedDirectoryEntriesGetDirectoryContent(): void { $this->sourceStorage->mkdir('/test'); $this->sourceStorage->mkdir('/test/' . self::NFD_NAME); @@ -230,7 +218,7 @@ class EncodingTest extends \Test\Files\Storage\Storage { $this->assertEquals(self::NFC_NAME, $content[0]['name']); } - public function testNormalizedGetMetaData() { + public function testNormalizedGetMetaData(): void { $this->sourceStorage->mkdir('/test'); $this->sourceStorage->mkdir('/test/' . self::NFD_NAME); @@ -240,4 +228,12 @@ class EncodingTest extends \Test\Files\Storage\Storage { $entry = $this->instance->getMetaData('/test/' . self::NFD_NAME); $this->assertEquals(self::NFC_NAME, $entry['name']); } + + /** + * Regression test of https://github.com/nextcloud/server/issues/50431 + */ + public function testNoMetadata() { + $this->assertNull($this->instance->getMetaData('/test/null')); + } + } diff --git a/tests/lib/Files/Storage/Wrapper/EncryptionTest.php b/tests/lib/Files/Storage/Wrapper/EncryptionTest.php index a6e0260fde6..3e643714300 100644 --- a/tests/lib/Files/Storage/Wrapper/EncryptionTest.php +++ b/tests/lib/Files/Storage/Wrapper/EncryptionTest.php @@ -1,15 +1,20 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ + namespace Test\Files\Storage\Wrapper; +use Exception; use OC\Encryption\Exceptions\ModuleDoesNotExistsException; -use OC\Encryption\Update; +use OC\Encryption\File; use OC\Encryption\Util; +use OC\Files\Cache\Cache; use OC\Files\Cache\CacheEntry; +use OC\Files\Mount\MountPoint; use OC\Files\Storage\Temporary; use OC\Files\Storage\Wrapper\Encryption; use OC\Files\View; @@ -23,6 +28,9 @@ use OCP\Files\Cache\ICache; use OCP\Files\Mount\IMountPoint; use OCP\ICacheFactory; use OCP\IConfig; +use OCP\ITempManager; +use OCP\Server; +use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; use Test\Files\Storage\Storage; @@ -30,95 +38,33 @@ class EncryptionTest extends Storage { /** * block size will always be 8192 for a PHP stream * @see https://bugs.php.net/bug.php?id=21641 - * @var integer - */ - protected $headerSize = 8192; - - /** - * @var Temporary - */ - private $sourceStorage; - - /** - * @var \OC\Files\Storage\Wrapper\Encryption | \PHPUnit\Framework\MockObject\MockObject */ + protected int $headerSize = 8192; + private Temporary $sourceStorage; + /** @var Encryption&MockObject */ protected $instance; - - /** - * @var \OC\Encryption\Keys\Storage | \PHPUnit\Framework\MockObject\MockObject - */ - private $keyStore; - - /** - * @var \OC\Encryption\Util | \PHPUnit\Framework\MockObject\MockObject - */ - private $util; - - /** - * @var \OC\Encryption\Manager | \PHPUnit\Framework\MockObject\MockObject - */ - private $encryptionManager; - - /** - * @var \OCP\Encryption\IEncryptionModule | \PHPUnit\Framework\MockObject\MockObject - */ - private $encryptionModule; - - /** - * @var \OC\Encryption\Update | \PHPUnit\Framework\MockObject\MockObject - */ - private $update; - - /** - * @var \OC\Files\Cache\Cache | \PHPUnit\Framework\MockObject\MockObject - */ - private $cache; - - /** - * @var \OC\Log | \PHPUnit\Framework\MockObject\MockObject - */ - private $logger; - - /** - * @var \OC\Encryption\File | \PHPUnit\Framework\MockObject\MockObject - */ - private $file; - - - /** - * @var \OC\Files\Mount\MountPoint | \PHPUnit\Framework\MockObject\MockObject - */ - private $mount; - - /** - * @var \OC\Files\Mount\Manager | \PHPUnit\Framework\MockObject\MockObject - */ - private $mountManager; - - /** - * @var \OC\Group\Manager | \PHPUnit\Framework\MockObject\MockObject - */ - private $groupManager; - - /** - * @var \OCP\IConfig | \PHPUnit\Framework\MockObject\MockObject - */ - private $config; - - /** @var \OC\Memcache\ArrayCache | \PHPUnit\Framework\MockObject\MockObject */ - private $arrayCache; - - - /** @var integer dummy unencrypted size */ - private $dummySize = -1; + private \OC\Encryption\Keys\Storage&MockObject $keyStore; + private Util&MockObject $util; + private \OC\Encryption\Manager&MockObject $encryptionManager; + private IEncryptionModule&MockObject $encryptionModule; + private Cache&MockObject $cache; + private LoggerInterface&MockObject $logger; + private File&MockObject $file; + private MountPoint&MockObject $mount; + private \OC\Files\Mount\Manager&MockObject $mountManager; + private \OC\Group\Manager&MockObject $groupManager; + private IConfig&MockObject $config; + private ArrayCache&MockObject $arrayCache; + /** dummy unencrypted size */ + private int $dummySize = -1; protected function setUp(): void { parent::setUp(); $mockModule = $this->buildMockModule(); - $this->encryptionManager = $this->getMockBuilder('\OC\Encryption\Manager') + $this->encryptionManager = $this->getMockBuilder(\OC\Encryption\Manager::class) ->disableOriginalConstructor() - ->setMethods(['getEncryptionModule', 'isEnabled']) + ->onlyMethods(['getEncryptionModule', 'isEnabled']) ->getMock(); $this->encryptionManager->expects($this->any()) ->method('getEncryptionModule') @@ -132,12 +78,13 @@ class EncryptionTest extends Storage { ->disableOriginalConstructor() ->getMock(); - $this->util = $this->getMockBuilder('\OC\Encryption\Util') - ->setMethods(['getUidAndFilename', 'isFile', 'isExcluded']) + $this->util = $this->getMockBuilder(Util::class) + ->onlyMethods(['getUidAndFilename', 'isFile', 'isExcluded', 'stripPartialFileExtension']) ->setConstructorArgs([new View(), new Manager( $this->config, $this->createMock(ICacheFactory::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(IEventDispatcher::class), + $this->createMock(LoggerInterface::class), ), $this->groupManager, $this->config, $this->arrayCache]) ->getMock(); $this->util->expects($this->any()) @@ -145,10 +92,15 @@ class EncryptionTest extends Storage { ->willReturnCallback(function ($path) { return ['user1', $path]; }); + $this->util->expects($this->any()) + ->method('stripPartialFileExtension') + ->willReturnCallback(function ($path) { + return $path; + }); - $this->file = $this->getMockBuilder('\OC\Encryption\File') + $this->file = $this->getMockBuilder(File::class) ->disableOriginalConstructor() - ->setMethods(['getAccessList']) + ->onlyMethods(['getAccessList']) ->getMock(); $this->file->expects($this->any())->method('getAccessList')->willReturn([]); @@ -156,15 +108,11 @@ class EncryptionTest extends Storage { $this->sourceStorage = new Temporary([]); - $this->keyStore = $this->getMockBuilder('\OC\Encryption\Keys\Storage') - ->disableOriginalConstructor()->getMock(); - - $this->update = $this->getMockBuilder('\OC\Encryption\Update') - ->disableOriginalConstructor()->getMock(); + $this->keyStore = $this->createMock(\OC\Encryption\Keys\Storage::class); - $this->mount = $this->getMockBuilder('\OC\Files\Mount\MountPoint') + $this->mount = $this->getMockBuilder(MountPoint::class) ->disableOriginalConstructor() - ->setMethods(['getOption']) + ->onlyMethods(['getOption']) ->getMock(); $this->mount->expects($this->any())->method('getOption')->willReturnCallback(function ($option, $default) { if ($option === 'encrypt' && $default === true) { @@ -188,7 +136,7 @@ class EncryptionTest extends Storage { $this->mountManager->method('findByStorageId') ->willReturn([]); - $this->instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption') + $this->instance = $this->getMockBuilder(Encryption::class) ->setConstructorArgs( [ [ @@ -197,10 +145,17 @@ class EncryptionTest extends Storage { 'mountPoint' => '/', 'mount' => $this->mount ], - $this->encryptionManager, $this->util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager, $this->arrayCache + $this->encryptionManager, + $this->util, + $this->logger, + $this->file, + null, + $this->keyStore, + $this->mountManager, + $this->arrayCache ] ) - ->setMethods(['getMetaData', 'getCache', 'getEncryptionModule']) + ->onlyMethods(['getMetaData', 'getCache', 'getEncryptionModule']) ->getMock(); $this->instance->expects($this->any()) @@ -218,13 +173,10 @@ class EncryptionTest extends Storage { ->willReturn($mockModule); } - /** - * @return \PHPUnit\Framework\MockObject\MockObject - */ - protected function buildMockModule() { + protected function buildMockModule(): IEncryptionModule&MockObject { $this->encryptionModule = $this->getMockBuilder('\OCP\Encryption\IEncryptionModule') ->disableOriginalConstructor() - ->setMethods(['getId', 'getDisplayName', 'begin', 'end', 'encrypt', 'decrypt', 'update', 'shouldEncrypt', 'getUnencryptedBlockSize', 'isReadable', 'encryptAll', 'prepareDecryptAll', 'isReadyForUser', 'needDetailedAccessList']) + ->onlyMethods(['getId', 'getDisplayName', 'begin', 'end', 'encrypt', 'decrypt', 'update', 'shouldEncrypt', 'getUnencryptedBlockSize', 'isReadable', 'encryptAll', 'prepareDecryptAll', 'isReadyForUser', 'needDetailedAccessList']) ->getMock(); $this->encryptionModule->expects($this->any())->method('getId')->willReturn('UNIT_TEST_MODULE'); @@ -242,7 +194,6 @@ class EncryptionTest extends Storage { } /** - * @dataProvider dataTestGetMetaData * * @param string $path * @param array $metaData @@ -251,7 +202,8 @@ class EncryptionTest extends Storage { * @param int $storedUnencryptedSize * @param array $expected */ - public function testGetMetaData($path, $metaData, $encrypted, $unencryptedSizeSet, $storedUnencryptedSize, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestGetMetaData')] + public function testGetMetaData($path, $metaData, $encrypted, $unencryptedSizeSet, $storedUnencryptedSize, $expected): void { $sourceStorage = $this->getMockBuilder('\OC\Files\Storage\Storage') ->disableOriginalConstructor()->getMock(); @@ -265,7 +217,7 @@ class EncryptionTest extends Storage { } ); - $this->instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption') + $this->instance = $this->getMockBuilder(Encryption::class) ->setConstructorArgs( [ [ @@ -274,10 +226,17 @@ class EncryptionTest extends Storage { 'mountPoint' => '/', 'mount' => $this->mount ], - $this->encryptionManager, $this->util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager, $this->arrayCache + $this->encryptionManager, + $this->util, + $this->logger, + $this->file, + null, + $this->keyStore, + $this->mountManager, + $this->arrayCache, ] ) - ->setMethods(['getCache', 'verifyUnencryptedSize']) + ->onlyMethods(['getCache', 'verifyUnencryptedSize']) ->getMock(); if ($unencryptedSizeSet) { @@ -320,7 +279,7 @@ class EncryptionTest extends Storage { } } - public function dataTestGetMetaData() { + public static function dataTestGetMetaData(): array { return [ ['/test.txt', ['size' => 42, 'encrypted' => 2, 'encryptedVersion' => 2, 'fileid' => 1], true, true, 12, ['size' => 12, 'encrypted' => true, 'encryptedVersion' => 2]], ['/test.txt', null, true, true, 12, null], @@ -329,14 +288,14 @@ class EncryptionTest extends Storage { ]; } - public function testFilesize() { + public function testFilesize(): void { $cache = $this->getMockBuilder('\OC\Files\Cache\Cache') ->disableOriginalConstructor()->getMock(); $cache->expects($this->any()) ->method('get') ->willReturn(new CacheEntry(['encrypted' => true, 'path' => '/test.txt', 'size' => 0, 'fileid' => 1])); - $this->instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption') + $this->instance = $this->getMockBuilder(Encryption::class) ->setConstructorArgs( [ [ @@ -345,10 +304,17 @@ class EncryptionTest extends Storage { 'mountPoint' => '/', 'mount' => $this->mount ], - $this->encryptionManager, $this->util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager, $this->arrayCache + $this->encryptionManager, + $this->util, + $this->logger, + $this->file, + null, + $this->keyStore, + $this->mountManager, + $this->arrayCache, ] ) - ->setMethods(['getCache', 'verifyUnencryptedSize']) + ->onlyMethods(['getCache', 'verifyUnencryptedSize']) ->getMock(); $this->instance->expects($this->any())->method('getCache')->willReturn($cache); @@ -362,18 +328,18 @@ class EncryptionTest extends Storage { } /** - * @dataProvider dataTestVerifyUnencryptedSize * * @param int $encryptedSize * @param int $unencryptedSize * @param bool $failure * @param int $expected */ - public function testVerifyUnencryptedSize($encryptedSize, $unencryptedSize, $failure, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestVerifyUnencryptedSize')] + public function testVerifyUnencryptedSize($encryptedSize, $unencryptedSize, $failure, $expected): void { $sourceStorage = $this->getMockBuilder('\OC\Files\Storage\Storage') ->disableOriginalConstructor()->getMock(); - $this->instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption') + $this->instance = $this->getMockBuilder(Encryption::class) ->setConstructorArgs( [ [ @@ -382,10 +348,17 @@ class EncryptionTest extends Storage { 'mountPoint' => '/', 'mount' => $this->mount ], - $this->encryptionManager, $this->util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager, $this->arrayCache + $this->encryptionManager, + $this->util, + $this->logger, + $this->file, + null, + $this->keyStore, + $this->mountManager, + $this->arrayCache, ] ) - ->setMethods(['fixUnencryptedSize']) + ->onlyMethods(['fixUnencryptedSize']) ->getMock(); $sourceStorage->expects($this->once())->method('filesize')->willReturn($encryptedSize); @@ -395,7 +368,7 @@ class EncryptionTest extends Storage { ->willReturnCallback( function () use ($failure, $expected) { if ($failure) { - throw new \Exception(); + throw new Exception(); } else { return $expected; } @@ -408,7 +381,7 @@ class EncryptionTest extends Storage { ); } - public function dataTestVerifyUnencryptedSize() { + public static function dataTestVerifyUnencryptedSize(): array { return [ [120, 80, false, 80], [120, 120, false, 80], @@ -418,17 +391,17 @@ class EncryptionTest extends Storage { } /** - * @dataProvider dataTestCopyAndRename * * @param string $source * @param string $target * @param $encryptionEnabled * @param boolean $renameKeysReturn */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestCopyAndRename')] public function testRename($source, $target, $encryptionEnabled, - $renameKeysReturn) { + $renameKeysReturn): void { if ($encryptionEnabled) { $this->keyStore ->expects($this->once()) @@ -448,7 +421,7 @@ class EncryptionTest extends Storage { $this->instance->rename($source, $target); } - public function testCopyEncryption() { + public function testCopyEncryption(): void { $this->instance->file_put_contents('source.txt', 'bar'); $this->instance->copy('source.txt', 'target.txt'); $this->assertSame('bar', $this->instance->file_get_contents('target.txt')); @@ -463,7 +436,7 @@ class EncryptionTest extends Storage { * * @return array */ - public function dataTestCopyAndRename() { + public static function dataTestCopyAndRename(): array { return [ ['source', 'target', true, false, false], ['source', 'target', true, true, false], @@ -473,38 +446,45 @@ class EncryptionTest extends Storage { ]; } - public function testIsLocal() { + public function testIsLocal(): void { $this->encryptionManager->expects($this->once()) ->method('isEnabled')->willReturn(true); $this->assertFalse($this->instance->isLocal()); } /** - * @dataProvider dataTestRmdir * * @param string $path * @param boolean $rmdirResult * @param boolean $isExcluded * @param boolean $encryptionEnabled */ - public function testRmdir($path, $rmdirResult, $isExcluded, $encryptionEnabled) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestRmdir')] + public function testRmdir($path, $rmdirResult, $isExcluded, $encryptionEnabled): void { $sourceStorage = $this->getMockBuilder('\OC\Files\Storage\Storage') ->disableOriginalConstructor()->getMock(); $util = $this->getMockBuilder('\OC\Encryption\Util')->disableOriginalConstructor()->getMock(); $sourceStorage->expects($this->once())->method('rmdir')->willReturn($rmdirResult); - $util->expects($this->any())->method('isExcluded')-> willReturn($isExcluded); + $util->expects($this->any())->method('isExcluded')->willReturn($isExcluded); $this->encryptionManager->expects($this->any())->method('isEnabled')->willReturn($encryptionEnabled); - $encryptionStorage = new \OC\Files\Storage\Wrapper\Encryption( + $encryptionStorage = new Encryption( [ 'storage' => $sourceStorage, 'root' => 'foo', 'mountPoint' => '/mountPoint', 'mount' => $this->mount ], - $this->encryptionManager, $util, $this->logger, $this->file, null, $this->keyStore, $this->update + $this->encryptionManager, + $util, + $this->logger, + $this->file, + null, + $this->keyStore, + $this->mountManager, + $this->arrayCache, ); @@ -517,7 +497,7 @@ class EncryptionTest extends Storage { $encryptionStorage->rmdir($path); } - public function dataTestRmdir() { + public static function dataTestRmdir(): array { return [ ['/file.txt', true, true, true], ['/file.txt', false, true, true], @@ -531,12 +511,12 @@ class EncryptionTest extends Storage { } /** - * @dataProvider dataTestCopyKeys * * @param boolean $excluded * @param boolean $expected */ - public function testCopyKeys($excluded, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestCopyKeys')] + public function testCopyKeys($excluded, $expected): void { $this->util->expects($this->once()) ->method('isExcluded') ->willReturn($excluded); @@ -552,7 +532,7 @@ class EncryptionTest extends Storage { ); } - public function dataTestCopyKeys() { + public static function dataTestCopyKeys(): array { return [ [true, false], [false, true], @@ -560,13 +540,13 @@ class EncryptionTest extends Storage { } /** - * @dataProvider dataTestGetHeader * * @param string $path * @param bool $strippedPathExists * @param string $strippedPath */ - public function testGetHeader($path, $strippedPathExists, $strippedPath) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestGetHeader')] + public function testGetHeader($path, $strippedPathExists, $strippedPath): void { $sourceStorage = $this->getMockBuilder('\OC\Files\Storage\Storage') ->disableOriginalConstructor()->getMock(); @@ -577,7 +557,8 @@ class EncryptionTest extends Storage { new Manager( $this->config, $this->createMock(ICacheFactory::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(IEventDispatcher::class), + $this->createMock(LoggerInterface::class), ), $this->groupManager, $this->config, @@ -593,7 +574,7 @@ class EncryptionTest extends Storage { return ['encrypted' => true, 'path' => $path]; }); - $instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption') + $instance = $this->getMockBuilder(Encryption::class) ->setConstructorArgs( [ [ @@ -602,10 +583,17 @@ class EncryptionTest extends Storage { 'mountPoint' => '/', 'mount' => $this->mount ], - $this->encryptionManager, $util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager, $this->arrayCache + $this->encryptionManager, + $util, + $this->logger, + $this->file, + null, + $this->keyStore, + $this->mountManager, + $this->arrayCache, ] ) - ->setMethods(['getCache', 'readFirstBlock']) + ->onlyMethods(['getCache', 'readFirstBlock']) ->getMock(); $instance->method('getCache')->willReturn($cache); @@ -631,7 +619,7 @@ class EncryptionTest extends Storage { $this->invokePrivate($instance, 'getHeader', [$path]); } - public function dataTestGetHeader() { + public static function dataTestGetHeader(): array { return [ ['/foo/bar.txt', false, '/foo/bar.txt'], ['/foo/bar.txt.part', false, '/foo/bar.txt'], @@ -644,34 +632,40 @@ class EncryptionTest extends Storage { /** * test if getHeader adds the default module correctly to the header for * legacy files - * - * @dataProvider dataTestGetHeaderAddLegacyModule */ - public function testGetHeaderAddLegacyModule($header, $isEncrypted, $exists, $expected) { - $sourceStorage = $this->getMockBuilder('\OC\Files\Storage\Storage') + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestGetHeaderAddLegacyModule')] + public function testGetHeaderAddLegacyModule($header, $isEncrypted, $strippedPathExists, $expected): void { + $sourceStorage = $this->getMockBuilder(\OC\Files\Storage\Storage::class) ->disableOriginalConstructor()->getMock(); $sourceStorage->expects($this->once()) ->method('is_file') - ->willReturn($exists); + ->with('test.txt') + ->willReturn($strippedPathExists); - $util = $this->getMockBuilder('\OC\Encryption\Util') + $util = $this->getMockBuilder(Util::class) + ->onlyMethods(['stripPartialFileExtension', 'parseRawHeader']) ->setConstructorArgs([new View(), new Manager( $this->config, $this->createMock(ICacheFactory::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(IEventDispatcher::class), + $this->createMock(LoggerInterface::class), ), $this->groupManager, $this->config, $this->arrayCache]) ->getMock(); + $util->expects($this->any()) + ->method('stripPartialFileExtension') + ->willReturnCallback(function ($path) { + return $path; + }); - $cache = $this->getMockBuilder('\OC\Files\Cache\Cache') - ->disableOriginalConstructor()->getMock(); + $cache = $this->createMock(Cache::class); $cache->expects($this->any()) ->method('get') ->willReturnCallback(function ($path) use ($isEncrypted) { return ['encrypted' => $isEncrypted, 'path' => $path]; }); - $instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption') + $instance = $this->getMockBuilder(Encryption::class) ->setConstructorArgs( [ [ @@ -680,10 +674,17 @@ class EncryptionTest extends Storage { 'mountPoint' => '/', 'mount' => $this->mount ], - $this->encryptionManager, $util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager, $this->arrayCache + $this->encryptionManager, + $util, + $this->logger, + $this->file, + null, + $this->keyStore, + $this->mountManager, + $this->arrayCache, ] ) - ->setMethods(['readFirstBlock', 'getCache']) + ->onlyMethods(['readFirstBlock', 'getCache']) ->getMock(); $instance->method('readFirstBlock')->willReturn(''); @@ -699,7 +700,7 @@ class EncryptionTest extends Storage { } } - public function dataTestGetHeaderAddLegacyModule() { + public static function dataTestGetHeaderAddLegacyModule(): array { return [ [['cipher' => 'AES-128'], true, true, ['cipher' => 'AES-128', Util::HEADER_ENCRYPTION_MODULE_KEY => 'OC_DEFAULT_MODULE']], [[], true, false, []], @@ -708,7 +709,7 @@ class EncryptionTest extends Storage { ]; } - public function dataCopyBetweenStorage() { + public static function dataCopyBetweenStorage(): array { return [ [true, true, true], [true, false, false], @@ -717,7 +718,7 @@ class EncryptionTest extends Storage { ]; } - public function testCopyBetweenStorageMinimumEncryptedVersion() { + public function testCopyBetweenStorageMinimumEncryptedVersion(): void { $storage2 = $this->createMock(\OC\Files\Storage\Storage::class); $sourceInternalPath = $targetInternalPath = 'file.txt'; @@ -726,7 +727,7 @@ class EncryptionTest extends Storage { $storage2->expects($this->any()) ->method('fopen') ->willReturnCallback(function ($path, $mode) { - $temp = \OC::$server->getTempManager(); + $temp = Server::get(ITempManager::class); return fopen($temp->getTemporaryFile(), $mode); }); $storage2->method('getId') @@ -760,13 +761,13 @@ class EncryptionTest extends Storage { } /** - * @dataProvider dataCopyBetweenStorage * * @param bool $encryptionEnabled * @param bool $mountPointEncryptionEnabled * @param bool $expectedEncrypted */ - public function testCopyBetweenStorage($encryptionEnabled, $mountPointEncryptionEnabled, $expectedEncrypted) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataCopyBetweenStorage')] + public function testCopyBetweenStorage($encryptionEnabled, $mountPointEncryptionEnabled, $expectedEncrypted): void { $storage2 = $this->createMock(\OC\Files\Storage\Storage::class); $sourceInternalPath = $targetInternalPath = 'file.txt'; @@ -775,7 +776,7 @@ class EncryptionTest extends Storage { $storage2->expects($this->any()) ->method('fopen') ->willReturnCallback(function ($path, $mode) { - $temp = \OC::$server->getTempManager(); + $temp = Server::get(ITempManager::class); return fopen($temp->getTemporaryFile(), $mode); }); $storage2->method('getId') @@ -820,14 +821,14 @@ class EncryptionTest extends Storage { } /** - * @dataProvider dataTestCopyBetweenStorageVersions * * @param string $sourceInternalPath * @param string $targetInternalPath * @param bool $copyResult * @param bool $encrypted */ - public function testCopyBetweenStorageVersions($sourceInternalPath, $targetInternalPath, $copyResult, $encrypted) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestCopyBetweenStorageVersions')] + public function testCopyBetweenStorageVersions($sourceInternalPath, $targetInternalPath, $copyResult, $encrypted): void { $sourceStorage = $this->createMock(\OC\Files\Storage\Storage::class); $targetStorage = $this->createMock(\OC\Files\Storage\Storage::class); @@ -837,8 +838,8 @@ class EncryptionTest extends Storage { $mountPoint = '/mountPoint'; - /** @var \OC\Files\Storage\Wrapper\Encryption |\PHPUnit\Framework\MockObject\MockObject $instance */ - $instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption') + /** @var Encryption |MockObject $instance */ + $instance = $this->getMockBuilder(Encryption::class) ->setConstructorArgs( [ [ @@ -853,12 +854,11 @@ class EncryptionTest extends Storage { $this->file, null, $this->keyStore, - $this->update, $this->mountManager, $this->arrayCache ] ) - ->setMethods(['updateUnencryptedSize', 'getCache']) + ->onlyMethods(['updateUnencryptedSize', 'getCache']) ->getMock(); $targetStorage->expects($this->once())->method('copyFromStorage') @@ -900,7 +900,7 @@ class EncryptionTest extends Storage { $this->assertSame($copyResult, $result); } - public function dataTestCopyBetweenStorageVersions() { + public static function dataTestCopyBetweenStorageVersions(): array { return [ ['/files/foo.txt', '/files_versions/foo.txt.768743', true, true], ['/files/foo.txt', '/files_versions/foo.txt.768743', true, false], @@ -915,17 +915,17 @@ class EncryptionTest extends Storage { } /** - * @dataProvider dataTestIsVersion * @param string $path * @param bool $expected */ - public function testIsVersion($path, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestIsVersion')] + public function testIsVersion($path, $expected): void { $this->assertSame($expected, $this->invokePrivate($this->instance, 'isVersion', [$path]) ); } - public function dataTestIsVersion() { + public static function dataTestIsVersion(): array { return [ ['files_versions/foo', true], ['/files_versions/foo', true], @@ -937,25 +937,23 @@ class EncryptionTest extends Storage { } /** - * @dataProvider dataTestShouldEncrypt * * @param bool $encryptMountPoint * @param mixed $encryptionModule * @param bool $encryptionModuleShouldEncrypt * @param bool $expected */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestShouldEncrypt')] public function testShouldEncrypt( $encryptMountPoint, $encryptionModule, $encryptionModuleShouldEncrypt, - $expected - ) { + $expected, + ): void { $encryptionManager = $this->createMock(\OC\Encryption\Manager::class); $util = $this->createMock(Util::class); $fileHelper = $this->createMock(IFile::class); - $uid = null; $keyStorage = $this->createMock(IStorage::class); - $update = $this->createMock(Update::class); $mountManager = $this->createMock(\OC\Files\Mount\Manager::class); $mount = $this->createMock(IMountPoint::class); $arrayCache = $this->createMock(ArrayCache::class); @@ -971,18 +969,17 @@ class EncryptionTest extends Storage { $util, $this->logger, $fileHelper, - $uid, + null, $keyStorage, - $update, $mountManager, $arrayCache ] ) - ->setMethods(['getFullPath', 'getEncryptionModule']) + ->onlyMethods(['getFullPath', 'getEncryptionModule']) ->getMock(); if ($encryptionModule === true) { - /** @var IEncryptionModule|\PHPUnit\Framework\MockObject\MockObject $encryptionModule */ + /** @var IEncryptionModule|MockObject $encryptionModule */ $encryptionModule = $this->createMock(IEncryptionModule::class); } @@ -1020,7 +1017,7 @@ class EncryptionTest extends Storage { $this->assertSame($expected, $result); } - public function dataTestShouldEncrypt() { + public static function dataTestShouldEncrypt(): array { return [ [false, false, false, false], [true, false, false, false], diff --git a/tests/lib/Files/Storage/Wrapper/JailTest.php b/tests/lib/Files/Storage/Wrapper/JailTest.php index c48f52ecce7..0043e37ba33 100644 --- a/tests/lib/Files/Storage/Wrapper/JailTest.php +++ b/tests/lib/Files/Storage/Wrapper/JailTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,17 +8,21 @@ namespace Test\Files\Storage\Wrapper; +use OC\Files\Filesystem; +use OC\Files\Storage\Temporary; +use OC\Files\Storage\Wrapper\Jail; + class JailTest extends \Test\Files\Storage\Storage { /** - * @var \OC\Files\Storage\Temporary + * @var Temporary */ private $sourceStorage; protected function setUp(): void { parent::setUp(); - $this->sourceStorage = new \OC\Files\Storage\Temporary([]); + $this->sourceStorage = new Temporary([]); $this->sourceStorage->mkdir('foo'); - $this->instance = new \OC\Files\Storage\Wrapper\Jail([ + $this->instance = new Jail([ 'storage' => $this->sourceStorage, 'root' => 'foo' ]); @@ -27,8 +32,8 @@ class JailTest extends \Test\Files\Storage\Storage { // test that nothing outside our jail is touched $contents = []; $dh = $this->sourceStorage->opendir(''); - while ($file = readdir($dh)) { - if (!\OC\Files\Filesystem::isIgnoredDir($file)) { + while (($file = readdir($dh)) !== false) { + if (!Filesystem::isIgnoredDir($file)) { $contents[] = $file; } } @@ -37,12 +42,12 @@ class JailTest extends \Test\Files\Storage\Storage { parent::tearDown(); } - public function testMkDirRooted() { + public function testMkDirRooted(): void { $this->instance->mkdir('bar'); $this->assertTrue($this->sourceStorage->is_dir('foo/bar')); } - public function testFilePutContentsRooted() { + public function testFilePutContentsRooted(): void { $this->instance->file_put_contents('bar', 'asd'); $this->assertEquals('asd', $this->sourceStorage->file_get_contents('foo/bar')); } diff --git a/tests/lib/Files/Storage/Wrapper/KnownMtimeTest.php b/tests/lib/Files/Storage/Wrapper/KnownMtimeTest.php index ccc95de1002..b1b5582b4ed 100644 --- a/tests/lib/Files/Storage/Wrapper/KnownMtimeTest.php +++ b/tests/lib/Files/Storage/Wrapper/KnownMtimeTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -50,7 +51,7 @@ class KnownMtimeTest extends Storage { ]); } - public function testNewerKnownMtime() { + public function testNewerKnownMtime(): void { $future = time() + 1000; $this->fakeTime = $future; diff --git a/tests/lib/Files/Storage/Wrapper/PermissionsMaskTest.php b/tests/lib/Files/Storage/Wrapper/PermissionsMaskTest.php index 0b2d444700a..a2f3460c58c 100644 --- a/tests/lib/Files/Storage/Wrapper/PermissionsMaskTest.php +++ b/tests/lib/Files/Storage/Wrapper/PermissionsMaskTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,6 +8,8 @@ namespace Test\Files\Storage\Wrapper; +use OC\Files\Storage\Temporary; +use OC\Files\Storage\Wrapper\PermissionsMask; use OC\Files\Storage\Wrapper\Wrapper; use OCP\Constants; use OCP\Files\Cache\IScanner; @@ -16,13 +19,13 @@ use OCP\Files\Cache\IScanner; */ class PermissionsMaskTest extends \Test\Files\Storage\Storage { /** - * @var \OC\Files\Storage\Temporary + * @var Temporary */ private $sourceStorage; protected function setUp(): void { parent::setUp(); - $this->sourceStorage = new \OC\Files\Storage\Temporary([]); + $this->sourceStorage = new Temporary([]); $this->instance = $this->getMaskedStorage(Constants::PERMISSION_ALL); } @@ -32,19 +35,19 @@ class PermissionsMaskTest extends \Test\Files\Storage\Storage { } protected function getMaskedStorage($mask) { - return new \OC\Files\Storage\Wrapper\PermissionsMask([ + return new PermissionsMask([ 'storage' => $this->sourceStorage, 'mask' => $mask ]); } - public function testMkdirNoCreate() { + public function testMkdirNoCreate(): void { $storage = $this->getMaskedStorage(Constants::PERMISSION_ALL - Constants::PERMISSION_CREATE); $this->assertFalse($storage->mkdir('foo')); $this->assertFalse($storage->file_exists('foo')); } - public function testRmdirNoDelete() { + public function testRmdirNoDelete(): void { $storage = $this->getMaskedStorage(Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE); $this->assertTrue($storage->mkdir('foo')); $this->assertTrue($storage->file_exists('foo')); @@ -52,25 +55,25 @@ class PermissionsMaskTest extends \Test\Files\Storage\Storage { $this->assertTrue($storage->file_exists('foo')); } - public function testTouchNewFileNoCreate() { + public function testTouchNewFileNoCreate(): void { $storage = $this->getMaskedStorage(Constants::PERMISSION_ALL - Constants::PERMISSION_CREATE); $this->assertFalse($storage->touch('foo')); $this->assertFalse($storage->file_exists('foo')); } - public function testTouchNewFileNoUpdate() { + public function testTouchNewFileNoUpdate(): void { $storage = $this->getMaskedStorage(Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE); $this->assertTrue($storage->touch('foo')); $this->assertTrue($storage->file_exists('foo')); } - public function testTouchExistingFileNoUpdate() { + public function testTouchExistingFileNoUpdate(): void { $this->sourceStorage->touch('foo'); $storage = $this->getMaskedStorage(Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE); $this->assertFalse($storage->touch('foo')); } - public function testUnlinkNoDelete() { + public function testUnlinkNoDelete(): void { $storage = $this->getMaskedStorage(Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE); $this->assertTrue($storage->touch('foo')); $this->assertTrue($storage->file_exists('foo')); @@ -78,35 +81,35 @@ class PermissionsMaskTest extends \Test\Files\Storage\Storage { $this->assertTrue($storage->file_exists('foo')); } - public function testPutContentsNewFileNoUpdate() { + public function testPutContentsNewFileNoUpdate(): void { $storage = $this->getMaskedStorage(Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE); $this->assertEquals(3, $storage->file_put_contents('foo', 'bar')); $this->assertEquals('bar', $storage->file_get_contents('foo')); } - public function testPutContentsNewFileNoCreate() { + public function testPutContentsNewFileNoCreate(): void { $storage = $this->getMaskedStorage(Constants::PERMISSION_ALL - Constants::PERMISSION_CREATE); $this->assertFalse($storage->file_put_contents('foo', 'bar')); } - public function testPutContentsExistingFileNoUpdate() { + public function testPutContentsExistingFileNoUpdate(): void { $this->sourceStorage->touch('foo'); $storage = $this->getMaskedStorage(Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE); $this->assertFalse($storage->file_put_contents('foo', 'bar')); } - public function testFopenExistingFileNoUpdate() { + public function testFopenExistingFileNoUpdate(): void { $this->sourceStorage->touch('foo'); $storage = $this->getMaskedStorage(Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE); $this->assertFalse($storage->fopen('foo', 'w')); } - public function testFopenNewFileNoCreate() { + public function testFopenNewFileNoCreate(): void { $storage = $this->getMaskedStorage(Constants::PERMISSION_ALL - Constants::PERMISSION_CREATE); $this->assertFalse($storage->fopen('foo', 'w')); } - public function testScanNewFiles() { + public function testScanNewFiles(): void { $storage = $this->getMaskedStorage(Constants::PERMISSION_READ + Constants::PERMISSION_CREATE); $storage->file_put_contents('foo', 'bar'); $storage->getScanner()->scan(''); @@ -115,7 +118,7 @@ class PermissionsMaskTest extends \Test\Files\Storage\Storage { $this->assertEquals(Constants::PERMISSION_READ, $storage->getCache()->get('foo')->getPermissions()); } - public function testScanNewWrappedFiles() { + public function testScanNewWrappedFiles(): void { $storage = $this->getMaskedStorage(Constants::PERMISSION_READ + Constants::PERMISSION_CREATE); $wrappedStorage = new Wrapper(['storage' => $storage]); $wrappedStorage->file_put_contents('foo', 'bar'); @@ -125,9 +128,9 @@ class PermissionsMaskTest extends \Test\Files\Storage\Storage { $this->assertEquals(Constants::PERMISSION_READ, $storage->getCache()->get('foo')->getPermissions()); } - public function testScanNewFilesNested() { + public function testScanNewFilesNested(): void { $storage = $this->getMaskedStorage(Constants::PERMISSION_READ + Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE); - $nestedStorage = new \OC\Files\Storage\Wrapper\PermissionsMask([ + $nestedStorage = new PermissionsMask([ 'storage' => $storage, 'mask' => Constants::PERMISSION_READ + Constants::PERMISSION_CREATE ]); @@ -140,7 +143,7 @@ class PermissionsMaskTest extends \Test\Files\Storage\Storage { $this->assertEquals(Constants::PERMISSION_READ, $wrappedStorage->getCache()->get('foo')->getPermissions()); } - public function testScanUnchanged() { + public function testScanUnchanged(): void { $this->sourceStorage->mkdir('foo'); $this->sourceStorage->file_put_contents('foo/bar.txt', 'bar'); @@ -149,7 +152,7 @@ class PermissionsMaskTest extends \Test\Files\Storage\Storage { $storage = $this->getMaskedStorage(Constants::PERMISSION_READ); $scanner = $storage->getScanner(); $called = false; - $scanner->listen('\OC\Files\Cache\Scanner', 'addToCache', function () use (&$called) { + $scanner->listen('\OC\Files\Cache\Scanner', 'addToCache', function () use (&$called): void { $called = true; }); $scanner->scan('foo', IScanner::SCAN_RECURSIVE, IScanner::REUSE_ETAG | IScanner::REUSE_SIZE); @@ -157,7 +160,7 @@ class PermissionsMaskTest extends \Test\Files\Storage\Storage { $this->assertFalse($called); } - public function testScanUnchangedWrapped() { + public function testScanUnchangedWrapped(): void { $this->sourceStorage->mkdir('foo'); $this->sourceStorage->file_put_contents('foo/bar.txt', 'bar'); @@ -167,7 +170,7 @@ class PermissionsMaskTest extends \Test\Files\Storage\Storage { $wrappedStorage = new Wrapper(['storage' => $storage]); $scanner = $wrappedStorage->getScanner(); $called = false; - $scanner->listen('\OC\Files\Cache\Scanner', 'addToCache', function () use (&$called) { + $scanner->listen('\OC\Files\Cache\Scanner', 'addToCache', function () use (&$called): void { $called = true; }); $scanner->scan('foo', IScanner::SCAN_RECURSIVE, IScanner::REUSE_ETAG | IScanner::REUSE_SIZE); diff --git a/tests/lib/Files/Storage/Wrapper/QuotaTest.php b/tests/lib/Files/Storage/Wrapper/QuotaTest.php index b24b44c6a56..2878fe6ca92 100644 --- a/tests/lib/Files/Storage/Wrapper/QuotaTest.php +++ b/tests/lib/Files/Storage/Wrapper/QuotaTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -10,8 +11,10 @@ namespace Test\Files\Storage\Wrapper; //ensure the constants are loaded use OC\Files\Cache\CacheEntry; use OC\Files\Storage\Local; - -\OC::$loader->load('\OC\Files\Filesystem'); +use OC\Files\Storage\Wrapper\Quota; +use OCP\Files; +use OCP\ITempManager; +use OCP\Server; /** * Class QuotaTest @@ -29,13 +32,13 @@ class QuotaTest extends \Test\Files\Storage\Storage { protected function setUp(): void { parent::setUp(); - $this->tmpDir = \OC::$server->getTempManager()->getTemporaryFolder(); - $storage = new \OC\Files\Storage\Local(['datadir' => $this->tmpDir]); - $this->instance = new \OC\Files\Storage\Wrapper\Quota(['storage' => $storage, 'quota' => 10000000]); + $this->tmpDir = Server::get(ITempManager::class)->getTemporaryFolder(); + $storage = new Local(['datadir' => $this->tmpDir]); + $this->instance = new Quota(['storage' => $storage, 'quota' => 10000000]); } protected function tearDown(): void { - \OC_Helper::rmdirr($this->tmpDir); + Files::rmdirr($this->tmpDir); parent::tearDown(); } @@ -43,30 +46,30 @@ class QuotaTest extends \Test\Files\Storage\Storage { * @param integer $limit */ protected function getLimitedStorage($limit) { - $storage = new \OC\Files\Storage\Local(['datadir' => $this->tmpDir]); + $storage = new Local(['datadir' => $this->tmpDir]); $storage->mkdir('files'); $storage->getScanner()->scan(''); - return new \OC\Files\Storage\Wrapper\Quota(['storage' => $storage, 'quota' => $limit]); + return new Quota(['storage' => $storage, 'quota' => $limit]); } - public function testFilePutContentsNotEnoughSpace() { + public function testFilePutContentsNotEnoughSpace(): void { $instance = $this->getLimitedStorage(3); $this->assertFalse($instance->file_put_contents('files/foo', 'foobar')); } - public function testCopyNotEnoughSpace() { + public function testCopyNotEnoughSpace(): void { $instance = $this->getLimitedStorage(9); $this->assertEquals(6, $instance->file_put_contents('files/foo', 'foobar')); $instance->getScanner()->scan(''); $this->assertFalse($instance->copy('files/foo', 'files/bar')); } - public function testFreeSpace() { + public function testFreeSpace(): void { $instance = $this->getLimitedStorage(9); $this->assertEquals(9, $instance->free_space('')); } - public function testFreeSpaceWithUsedSpace() { + public function testFreeSpaceWithUsedSpace(): void { $instance = $this->getLimitedStorage(9); $instance->getCache()->put( '', ['size' => 3] @@ -74,9 +77,9 @@ class QuotaTest extends \Test\Files\Storage\Storage { $this->assertEquals(6, $instance->free_space('')); } - public function testFreeSpaceWithUnknownDiskSpace() { + public function testFreeSpaceWithUnknownDiskSpace(): void { $storage = $this->getMockBuilder(Local::class) - ->setMethods(['free_space']) + ->onlyMethods(['free_space']) ->setConstructorArgs([['datadir' => $this->tmpDir]]) ->getMock(); $storage->expects($this->any()) @@ -84,14 +87,14 @@ class QuotaTest extends \Test\Files\Storage\Storage { ->willReturn(-2); $storage->getScanner()->scan(''); - $instance = new \OC\Files\Storage\Wrapper\Quota(['storage' => $storage, 'quota' => 9]); + $instance = new Quota(['storage' => $storage, 'quota' => 9]); $instance->getCache()->put( '', ['size' => 3] ); $this->assertEquals(6, $instance->free_space('')); } - public function testFreeSpaceWithUsedSpaceAndEncryption() { + public function testFreeSpaceWithUsedSpaceAndEncryption(): void { $instance = $this->getLimitedStorage(9); $instance->getCache()->put( '', ['size' => 7] @@ -99,7 +102,7 @@ class QuotaTest extends \Test\Files\Storage\Storage { $this->assertEquals(2, $instance->free_space('')); } - public function testFWriteNotEnoughSpace() { + public function testFWriteNotEnoughSpace(): void { $instance = $this->getLimitedStorage(9); $stream = $instance->fopen('files/foo', 'w+'); $this->assertEquals(6, fwrite($stream, 'foobar')); @@ -108,7 +111,7 @@ class QuotaTest extends \Test\Files\Storage\Storage { $this->assertEquals('foobarqwe', $instance->file_get_contents('files/foo')); } - public function testStreamCopyWithEnoughSpace() { + public function testStreamCopyWithEnoughSpace(): void { $instance = $this->getLimitedStorage(16); $inputStream = fopen('data://text/plain,foobarqwerty', 'r'); $outputStream = $instance->fopen('files/foo', 'w+'); @@ -119,7 +122,7 @@ class QuotaTest extends \Test\Files\Storage\Storage { fclose($outputStream); } - public function testStreamCopyNotEnoughSpace() { + public function testStreamCopyNotEnoughSpace(): void { $instance = $this->getLimitedStorage(9); $inputStream = fopen('data://text/plain,foobarqwerty', 'r'); $outputStream = $instance->fopen('files/foo', 'w+'); @@ -130,21 +133,21 @@ class QuotaTest extends \Test\Files\Storage\Storage { fclose($outputStream); } - public function testReturnFalseWhenFopenFailed() { + public function testReturnFalseWhenFopenFailed(): void { $failStorage = $this->getMockBuilder(Local::class) - ->setMethods(['fopen']) + ->onlyMethods(['fopen']) ->setConstructorArgs([['datadir' => $this->tmpDir]]) ->getMock(); $failStorage->expects($this->any()) ->method('fopen') ->willReturn(false); - $instance = new \OC\Files\Storage\Wrapper\Quota(['storage' => $failStorage, 'quota' => 1000]); + $instance = new Quota(['storage' => $failStorage, 'quota' => 1000]); $this->assertFalse($instance->fopen('failedfopen', 'r')); } - public function testReturnRegularStreamOnRead() { + public function testReturnRegularStreamOnRead(): void { $instance = $this->getLimitedStorage(9); // create test file first @@ -163,7 +166,7 @@ class QuotaTest extends \Test\Files\Storage\Storage { fclose($stream); } - public function testReturnRegularStreamWhenOutsideFiles() { + public function testReturnRegularStreamWhenOutsideFiles(): void { $instance = $this->getLimitedStorage(9); $instance->mkdir('files_other'); @@ -174,7 +177,7 @@ class QuotaTest extends \Test\Files\Storage\Storage { fclose($stream); } - public function testReturnQuotaStreamOnWrite() { + public function testReturnQuotaStreamOnWrite(): void { $instance = $this->getLimitedStorage(9); $stream = $instance->fopen('files/foo', 'w+'); $meta = stream_get_meta_data($stream); @@ -183,7 +186,7 @@ class QuotaTest extends \Test\Files\Storage\Storage { fclose($stream); } - public function testSpaceRoot() { + public function testSpaceRoot(): void { $storage = $this->getMockBuilder(Local::class)->disableOriginalConstructor()->getMock(); $cache = $this->getMockBuilder('\OC\Files\Cache\Cache')->disableOriginalConstructor()->getMock(); $storage->expects($this->once()) @@ -197,24 +200,24 @@ class QuotaTest extends \Test\Files\Storage\Storage { ->with('files') ->willReturn(new CacheEntry(['size' => 50])); - $instance = new \OC\Files\Storage\Wrapper\Quota(['storage' => $storage, 'quota' => 1024, 'root' => 'files']); + $instance = new Quota(['storage' => $storage, 'quota' => 1024, 'root' => 'files']); $this->assertEquals(1024 - 50, $instance->free_space('')); } - public function testInstanceOfStorageWrapper() { + public function testInstanceOfStorageWrapper(): void { $this->assertTrue($this->instance->instanceOfStorage('\OC\Files\Storage\Local')); $this->assertTrue($this->instance->instanceOfStorage('\OC\Files\Storage\Wrapper\Wrapper')); $this->assertTrue($this->instance->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')); } - public function testNoMkdirQuotaZero() { + public function testNoMkdirQuotaZero(): void { $instance = $this->getLimitedStorage(0.0); $this->assertFalse($instance->mkdir('files')); $this->assertFalse($instance->mkdir('files/foobar')); } - public function testMkdirQuotaZeroTrashbin() { + public function testMkdirQuotaZeroTrashbin(): void { $instance = $this->getLimitedStorage(0.0); $this->assertTrue($instance->mkdir('files_trashbin')); $this->assertTrue($instance->mkdir('files_trashbin/files')); @@ -222,7 +225,7 @@ class QuotaTest extends \Test\Files\Storage\Storage { $this->assertTrue($instance->mkdir('cache')); } - public function testNoTouchQuotaZero() { + public function testNoTouchQuotaZero(): void { $instance = $this->getLimitedStorage(0.0); $this->assertFalse($instance->touch('foobar')); } diff --git a/tests/lib/Files/Storage/Wrapper/WrapperTest.php b/tests/lib/Files/Storage/Wrapper/WrapperTest.php index 0244c78da8b..60f139450c7 100644 --- a/tests/lib/Files/Storage/Wrapper/WrapperTest.php +++ b/tests/lib/Files/Storage/Wrapper/WrapperTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,6 +8,12 @@ namespace Test\Files\Storage\Wrapper; +use OC\Files\Storage\Local; +use OC\Files\Storage\Wrapper\Wrapper; +use OCP\Files; +use OCP\ITempManager; +use OCP\Server; + class WrapperTest extends \Test\Files\Storage\Storage { /** * @var string tmpDir @@ -16,17 +23,17 @@ class WrapperTest extends \Test\Files\Storage\Storage { protected function setUp(): void { parent::setUp(); - $this->tmpDir = \OC::$server->getTempManager()->getTemporaryFolder(); - $storage = new \OC\Files\Storage\Local(['datadir' => $this->tmpDir]); - $this->instance = new \OC\Files\Storage\Wrapper\Wrapper(['storage' => $storage]); + $this->tmpDir = Server::get(ITempManager::class)->getTemporaryFolder(); + $storage = new Local(['datadir' => $this->tmpDir]); + $this->instance = new Wrapper(['storage' => $storage]); } protected function tearDown(): void { - \OC_Helper::rmdirr($this->tmpDir); + Files::rmdirr($this->tmpDir); parent::tearDown(); } - public function testInstanceOfStorageWrapper() { + public function testInstanceOfStorageWrapper(): void { $this->assertTrue($this->instance->instanceOfStorage('\OC\Files\Storage\Local')); $this->assertTrue($this->instance->instanceOfStorage('\OC\Files\Storage\Wrapper\Wrapper')); } diff --git a/tests/lib/Files/Stream/DummyEncryptionWrapper.php b/tests/lib/Files/Stream/DummyEncryptionWrapper.php index 211050905bd..89904e6de73 100644 --- a/tests/lib/Files/Stream/DummyEncryptionWrapper.php +++ b/tests/lib/Files/Stream/DummyEncryptionWrapper.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,7 +8,9 @@ namespace Test\Files\Stream; -class DummyEncryptionWrapper extends \OC\Files\Stream\Encryption { +use OC\Files\Stream\Encryption; + +class DummyEncryptionWrapper extends Encryption { /** * simulate a non-seekable stream wrapper by always return false * diff --git a/tests/lib/Files/Stream/EncryptionTest.php b/tests/lib/Files/Stream/EncryptionTest.php index b6650b56a85..62eaab3cc7e 100644 --- a/tests/lib/Files/Stream/EncryptionTest.php +++ b/tests/lib/Files/Stream/EncryptionTest.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -6,27 +9,32 @@ */ namespace Test\Files\Stream; +use OC\Encryption\File; +use OC\Encryption\Util; use OC\Files\Cache\CacheEntry; +use OC\Files\Storage\Storage; +use OC\Files\Storage\Wrapper\Wrapper; +use OC\Files\Stream\Encryption; use OC\Files\View; use OC\Memcache\ArrayCache; +use OCP\Encryption\IEncryptionModule; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Cache\ICache; use OCP\ICacheFactory; use OCP\IConfig; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; class EncryptionTest extends \Test\TestCase { public const DEFAULT_WRAPPER = '\OC\Files\Stream\Encryption'; - /** @var \OCP\Encryption\IEncryptionModule | \PHPUnit\Framework\MockObject\MockObject */ - private $encryptionModule; + private IEncryptionModule&MockObject $encryptionModule; /** - * @param string $fileName - * @param string $mode - * @param integer $unencryptedSize + * @param class-string<Wrapper> $wrapper * @return resource */ - protected function getStream($fileName, $mode, $unencryptedSize, $wrapper = self::DEFAULT_WRAPPER, $unencryptedSizeOnClose = 0) { + protected function getStream(string $fileName, string $mode, int $unencryptedSize, string $wrapper = self::DEFAULT_WRAPPER, int $unencryptedSizeOnClose = 0) { clearstatcache(); $size = filesize($fileName); $source = fopen($fileName, $mode); @@ -49,15 +57,16 @@ class EncryptionTest extends \Test\TestCase { ->getMock(); $file = $this->getMockBuilder('\OC\Encryption\File') ->disableOriginalConstructor() - ->setMethods(['getAccessList']) + ->onlyMethods(['getAccessList']) ->getMock(); $file->expects($this->any())->method('getAccessList')->willReturn([]); $util = $this->getMockBuilder('\OC\Encryption\Util') - ->setMethods(['getUidAndFilename']) + ->onlyMethods(['getUidAndFilename']) ->setConstructorArgs([new View(), new \OC\User\Manager( $config, $this->createMock(ICacheFactory::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(IEventDispatcher::class), + $this->createMock(LoggerInterface::class), ), $groupManager, $config, $arrayCache]) ->getMock(); $util->expects($this->any()) @@ -72,38 +81,49 @@ class EncryptionTest extends \Test\TestCase { $cache->expects($this->any())->method('get')->willReturn($entry); $cache->expects($this->any())->method('update')->with(5, ['encrypted' => 3, 'encryptedVersion' => 3, 'unencrypted_size' => $unencryptedSizeOnClose]); - - return $wrapper::wrap($source, $internalPath, - $fullPath, $header, $uid, $this->encryptionModule, $storage, $encStorage, - $util, $file, $mode, $size, $unencryptedSize, 8192, $wrapper); + return $wrapper::wrap( + $source, + $internalPath, + $fullPath, + $header, + $uid, + $this->encryptionModule, + $storage, + $encStorage, + $util, + $file, + $mode, + $size, + $unencryptedSize, + 8192, + true, + $wrapper, + ); } - /** - * @dataProvider dataProviderStreamOpen() - */ - public function testStreamOpen($isMasterKeyUsed, + #[\PHPUnit\Framework\Attributes\DataProvider('dataProviderStreamOpen')] + public function testStreamOpen( + $isMasterKeyUsed, $mode, $fullPath, $fileExists, $expectedSharePath, $expectedSize, $expectedUnencryptedSize, - $expectedReadOnly) { + $expectedReadOnly, + ): void { // build mocks - $encryptionModuleMock = $this->getMockBuilder('\OCP\Encryption\IEncryptionModule') - ->disableOriginalConstructor()->getMock(); + $encryptionModuleMock = $this->createMock(IEncryptionModule::class); $encryptionModuleMock->expects($this->any())->method('needDetailedAccessList')->willReturn(!$isMasterKeyUsed); $encryptionModuleMock->expects($this->once()) ->method('getUnencryptedBlockSize')->willReturn(99); $encryptionModuleMock->expects($this->once()) - ->method('begin')->willReturn(true); + ->method('begin')->willReturn([]); - $storageMock = $this->getMockBuilder('\OC\Files\Storage\Storage') - ->disableOriginalConstructor()->getMock(); + $storageMock = $this->createMock(Storage::class); $storageMock->expects($this->once())->method('file_exists')->willReturn($fileExists); - $fileMock = $this->getMockBuilder('\OC\Encryption\File') - ->disableOriginalConstructor()->getMock(); + $fileMock = $this->createMock(File::class); if ($isMasterKeyUsed) { $fileMock->expects($this->never())->method('getAccessList'); } else { @@ -113,18 +133,20 @@ class EncryptionTest extends \Test\TestCase { return []; }); } - $utilMock = $this->getMockBuilder('\OC\Encryption\Util') + $utilMock = $this->getMockBuilder(Util::class) ->disableOriginalConstructor()->getMock(); $utilMock->expects($this->any()) ->method('getHeaderSize') ->willReturn(8192); // get a instance of the stream wrapper - $streamWrapper = $this->getMockBuilder('\OC\Files\Stream\Encryption') - ->setMethods(['loadContext', 'writeHeader', 'skipHeader'])->disableOriginalConstructor()->getMock(); + $streamWrapper = $this->getMockBuilder(Encryption::class) + ->onlyMethods(['loadContext', 'writeHeader', 'skipHeader']) + ->disableOriginalConstructor() + ->getMock(); // set internal properties of the stream wrapper - $stream = new \ReflectionClass('\OC\Files\Stream\Encryption'); + $stream = new \ReflectionClass(Encryption::class); $encryptionModule = $stream->getProperty('encryptionModule'); $encryptionModule->setAccessible(true); $encryptionModule->setValue($streamWrapper, $encryptionModuleMock); @@ -150,6 +172,8 @@ class EncryptionTest extends \Test\TestCase { $header->setValue($streamWrapper, []); $header->setAccessible(false); $this->invokePrivate($streamWrapper, 'signed', [true]); + $this->invokePrivate($streamWrapper, 'internalPath', [$fullPath]); + $this->invokePrivate($streamWrapper, 'uid', ['test']); // call stream_open, that's the method we want to test $dummyVar = 'foo'; @@ -158,27 +182,21 @@ class EncryptionTest extends \Test\TestCase { // check internal properties $size = $stream->getProperty('size'); $size->setAccessible(true); - $this->assertSame($expectedSize, - $size->getValue($streamWrapper) - ); + $this->assertSame($expectedSize, $size->getValue($streamWrapper)); $size->setAccessible(false); $unencryptedSize = $stream->getProperty('unencryptedSize'); $unencryptedSize->setAccessible(true); - $this->assertSame($expectedUnencryptedSize, - $unencryptedSize->getValue($streamWrapper) - ); + $this->assertSame($expectedUnencryptedSize, $unencryptedSize->getValue($streamWrapper)); $unencryptedSize->setAccessible(false); $readOnly = $stream->getProperty('readOnly'); $readOnly->setAccessible(true); - $this->assertSame($expectedReadOnly, - $readOnly->getValue($streamWrapper) - ); + $this->assertSame($expectedReadOnly, $readOnly->getValue($streamWrapper)); $readOnly->setAccessible(false); } - public function dataProviderStreamOpen() { + public static function dataProviderStreamOpen(): array { return [ [false, 'r', '/foo/bar/test.txt', true, '/foo/bar/test.txt', null, null, true], [false, 'r', '/foo/bar/test.txt', false, '/foo/bar', null, null, true], @@ -189,8 +207,8 @@ class EncryptionTest extends \Test\TestCase { ]; } - public function testWriteRead() { - $fileName = tempnam("/tmp", "FOO"); + public function testWriteRead(): void { + $fileName = tempnam('/tmp', 'FOO'); $stream = $this->getStream($fileName, 'w+', 0, self::DEFAULT_WRAPPER, 6); $this->assertEquals(6, fwrite($stream, 'foobar')); fclose($stream); @@ -210,8 +228,8 @@ class EncryptionTest extends \Test\TestCase { unlink($fileName); } - public function testRewind() { - $fileName = tempnam("/tmp", "FOO"); + public function testRewind(): void { + $fileName = tempnam('/tmp', 'FOO'); $stream = $this->getStream($fileName, 'w+', 0, self::DEFAULT_WRAPPER, 6); $this->assertEquals(6, fwrite($stream, 'foobar')); $this->assertEquals(true, rewind($stream)); @@ -227,8 +245,8 @@ class EncryptionTest extends \Test\TestCase { unlink($fileName); } - public function testSeek() { - $fileName = tempnam("/tmp", "FOO"); + public function testSeek(): void { + $fileName = tempnam('/tmp', 'FOO'); $stream = $this->getStream($fileName, 'w+', 0, self::DEFAULT_WRAPPER, 9); $this->assertEquals(6, fwrite($stream, 'foobar')); @@ -249,7 +267,7 @@ class EncryptionTest extends \Test\TestCase { unlink($fileName); } - public function dataFilesProvider() { + public static function dataFilesProvider(): array { return [ ['lorem-big.txt'], ['block-aligned.txt'], @@ -257,13 +275,11 @@ class EncryptionTest extends \Test\TestCase { ]; } - /** - * @dataProvider dataFilesProvider - */ - public function testWriteReadBigFile($testFile) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataFilesProvider')] + public function testWriteReadBigFile($testFile): void { $expectedData = file_get_contents(\OC::$SERVERROOT . '/tests/data/' . $testFile); // write it - $fileName = tempnam("/tmp", "FOO"); + $fileName = tempnam('/tmp', 'FOO'); $stream = $this->getStream($fileName, 'w+', 0, self::DEFAULT_WRAPPER, strlen($expectedData)); // while writing the file from the beginning to the end we should never try // to read parts of the file. This should only happen for write operations @@ -294,17 +310,19 @@ class EncryptionTest extends \Test\TestCase { /** * simulate a non-seekable storage - * - * @dataProvider dataFilesProvider */ - public function testWriteToNonSeekableStorage($testFile) { - $wrapper = $this->getMockBuilder('\OC\Files\Stream\Encryption') - ->setMethods(['parentSeekStream'])->getMock(); - $wrapper->expects($this->any())->method('parentSeekStream')->willReturn(false); + #[\PHPUnit\Framework\Attributes\DataProvider('dataFilesProvider')] + public function testWriteToNonSeekableStorage($testFile): void { + $wrapper = $this->getMockBuilder(Encryption::class) + ->onlyMethods(['parentStreamSeek']) + ->getMock(); + $wrapper->expects($this->any()) + ->method('parentStreamSeek') + ->willReturn(false); $expectedData = file_get_contents(\OC::$SERVERROOT . '/tests/data/' . $testFile); // write it - $fileName = tempnam("/tmp", "FOO"); + $fileName = tempnam('/tmp', 'FOO'); $stream = $this->getStream($fileName, 'w+', 0, '\Test\Files\Stream\DummyEncryptionWrapper', strlen($expectedData)); // while writing the file from the beginning to the end we should never try // to read parts of the file. This should only happen for write operations @@ -333,13 +351,10 @@ class EncryptionTest extends \Test\TestCase { unlink($fileName); } - /** - * @return \PHPUnit\Framework\MockObject\MockObject - */ - protected function buildMockModule() { - $encryptionModule = $this->getMockBuilder('\OCP\Encryption\IEncryptionModule') + protected function buildMockModule(): IEncryptionModule&MockObject { + $encryptionModule = $this->getMockBuilder(IEncryptionModule::class) ->disableOriginalConstructor() - ->setMethods(['getId', 'getDisplayName', 'begin', 'end', 'encrypt', 'decrypt', 'update', 'shouldEncrypt', 'getUnencryptedBlockSize', 'isReadable', 'encryptAll', 'prepareDecryptAll', 'isReadyForUser', 'needDetailedAccessList']) + ->onlyMethods(['getId', 'getDisplayName', 'begin', 'end', 'encrypt', 'decrypt', 'update', 'shouldEncrypt', 'getUnencryptedBlockSize', 'isReadable', 'encryptAll', 'prepareDecryptAll', 'isReadyForUser', 'needDetailedAccessList']) ->getMock(); $encryptionModule->expects($this->any())->method('getId')->willReturn('UNIT_TEST_MODULE'); diff --git a/tests/lib/Files/Stream/HashWrapperTest.php b/tests/lib/Files/Stream/HashWrapperTest.php index 686fcbec82a..459bc5c4318 100644 --- a/tests/lib/Files/Stream/HashWrapperTest.php +++ b/tests/lib/Files/Stream/HashWrapperTest.php @@ -12,10 +12,8 @@ use OC\Files\Stream\HashWrapper; use Test\TestCase; class HashWrapperTest extends TestCase { - /** - * @dataProvider hashProvider - */ - public function testHashStream($data, string $algo, string $hash) { + #[\PHPUnit\Framework\Attributes\DataProvider('hashProvider')] + public function testHashStream($data, string $algo, string $hash): void { if (!is_resource($data)) { $tmpData = fopen('php://temp', 'r+'); if ($data !== null) { @@ -25,13 +23,13 @@ class HashWrapperTest extends TestCase { $data = $tmpData; } - $wrapper = HashWrapper::wrap($data, $algo, function ($result) use ($hash) { + $wrapper = HashWrapper::wrap($data, $algo, function ($result) use ($hash): void { $this->assertEquals($hash, $result); }); stream_get_contents($wrapper); } - public function hashProvider() { + public static function hashProvider(): array { return [ ['foo', 'md5', 'acbd18db4cc2f85cedef654fccc4a4d8'], ['foo', 'sha1', '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'], diff --git a/tests/lib/Files/Stream/QuotaTest.php b/tests/lib/Files/Stream/QuotaTest.php index 17ad14b7e44..4248d14f5a1 100644 --- a/tests/lib/Files/Stream/QuotaTest.php +++ b/tests/lib/Files/Stream/QuotaTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,6 +8,8 @@ namespace Test\Files\Stream; +use OC\Files\Stream\Quota; + class QuotaTest extends \Test\TestCase { /** * @param string $mode @@ -15,24 +18,24 @@ class QuotaTest extends \Test\TestCase { */ protected function getStream($mode, $limit) { $source = fopen('php://temp', $mode); - return \OC\Files\Stream\Quota::wrap($source, $limit); + return Quota::wrap($source, $limit); } - public function testWriteEnoughSpace() { + public function testWriteEnoughSpace(): void { $stream = $this->getStream('w+', 100); $this->assertEquals(6, fwrite($stream, 'foobar')); rewind($stream); $this->assertEquals('foobar', fread($stream, 100)); } - public function testWriteNotEnoughSpace() { + public function testWriteNotEnoughSpace(): void { $stream = $this->getStream('w+', 3); $this->assertEquals(3, fwrite($stream, 'foobar')); rewind($stream); $this->assertEquals('foo', fread($stream, 100)); } - public function testWriteNotEnoughSpaceSecondTime() { + public function testWriteNotEnoughSpaceSecondTime(): void { $stream = $this->getStream('w+', 9); $this->assertEquals(6, fwrite($stream, 'foobar')); $this->assertEquals(3, fwrite($stream, 'qwerty')); @@ -40,7 +43,7 @@ class QuotaTest extends \Test\TestCase { $this->assertEquals('foobarqwe', fread($stream, 100)); } - public function testWriteEnoughSpaceRewind() { + public function testWriteEnoughSpaceRewind(): void { $stream = $this->getStream('w+', 6); $this->assertEquals(6, fwrite($stream, 'foobar')); rewind($stream); @@ -49,7 +52,7 @@ class QuotaTest extends \Test\TestCase { $this->assertEquals('qwebar', fread($stream, 100)); } - public function testWriteNotEnoughSpaceRead() { + public function testWriteNotEnoughSpaceRead(): void { $stream = $this->getStream('w+', 6); $this->assertEquals(6, fwrite($stream, 'foobar')); rewind($stream); @@ -57,26 +60,26 @@ class QuotaTest extends \Test\TestCase { $this->assertEquals(0, fwrite($stream, 'qwe')); } - public function testWriteNotEnoughSpaceExistingStream() { + public function testWriteNotEnoughSpaceExistingStream(): void { $source = fopen('php://temp', 'w+'); fwrite($source, 'foobar'); - $stream = \OC\Files\Stream\Quota::wrap($source, 3); + $stream = Quota::wrap($source, 3); $this->assertEquals(3, fwrite($stream, 'foobar')); rewind($stream); $this->assertEquals('foobarfoo', fread($stream, 100)); } - public function testWriteNotEnoughSpaceExistingStreamRewind() { + public function testWriteNotEnoughSpaceExistingStreamRewind(): void { $source = fopen('php://temp', 'w+'); fwrite($source, 'foobar'); - $stream = \OC\Files\Stream\Quota::wrap($source, 3); + $stream = Quota::wrap($source, 3); rewind($stream); $this->assertEquals(6, fwrite($stream, 'qwerty')); rewind($stream); $this->assertEquals('qwerty', fread($stream, 100)); } - public function testFseekReturnsSuccess() { + public function testFseekReturnsSuccess(): void { $stream = $this->getStream('w+', 100); fwrite($stream, '0123456789'); $this->assertEquals(0, fseek($stream, 3, SEEK_SET)); @@ -84,7 +87,7 @@ class QuotaTest extends \Test\TestCase { $this->assertEquals(0, fseek($stream, -4, SEEK_END)); } - public function testWriteAfterSeekEndWithEnoughSpace() { + public function testWriteAfterSeekEndWithEnoughSpace(): void { $stream = $this->getStream('w+', 100); fwrite($stream, '0123456789'); fseek($stream, -3, SEEK_END); @@ -93,7 +96,7 @@ class QuotaTest extends \Test\TestCase { $this->assertEquals('0123456abcdefghijk', fread($stream, 100)); } - public function testWriteAfterSeekEndWithNotEnoughSpace() { + public function testWriteAfterSeekEndWithNotEnoughSpace(): void { $stream = $this->getStream('w+', 13); fwrite($stream, '0123456789'); // seek forward first to potentially week out @@ -106,7 +109,7 @@ class QuotaTest extends \Test\TestCase { $this->assertEquals('0123456abcdef', fread($stream, 100)); } - public function testWriteAfterSeekSetWithEnoughSpace() { + public function testWriteAfterSeekSetWithEnoughSpace(): void { $stream = $this->getStream('w+', 100); fwrite($stream, '0123456789'); fseek($stream, 7, SEEK_SET); @@ -115,7 +118,7 @@ class QuotaTest extends \Test\TestCase { $this->assertEquals('0123456abcdefghijk', fread($stream, 100)); } - public function testWriteAfterSeekSetWithNotEnoughSpace() { + public function testWriteAfterSeekSetWithNotEnoughSpace(): void { $stream = $this->getStream('w+', 13); fwrite($stream, '0123456789'); fseek($stream, 7, SEEK_SET); @@ -124,7 +127,7 @@ class QuotaTest extends \Test\TestCase { $this->assertEquals('0123456abcdef', fread($stream, 100)); } - public function testWriteAfterSeekCurWithEnoughSpace() { + public function testWriteAfterSeekCurWithEnoughSpace(): void { $stream = $this->getStream('w+', 100); fwrite($stream, '0123456789'); rewind($stream); @@ -136,7 +139,7 @@ class QuotaTest extends \Test\TestCase { $this->assertEquals('0123456abcdefghijk', fread($stream, 100)); } - public function testWriteAfterSeekCurWithNotEnoughSpace() { + public function testWriteAfterSeekCurWithNotEnoughSpace(): void { $stream = $this->getStream('w+', 13); fwrite($stream, '0123456789'); rewind($stream); diff --git a/tests/lib/Files/Type/DetectionTest.php b/tests/lib/Files/Type/DetectionTest.php index e647fa064d4..c30b21de401 100644 --- a/tests/lib/Files/Type/DetectionTest.php +++ b/tests/lib/Files/Type/DetectionTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -9,6 +10,7 @@ namespace Test\Files\Type; use OC\Files\Type\Detection; use OCP\IURLGenerator; +use OCP\Server; use Psr\Log\LoggerInterface; class DetectionTest extends \Test\TestCase { @@ -18,14 +20,14 @@ class DetectionTest extends \Test\TestCase { protected function setUp(): void { parent::setUp(); $this->detection = new Detection( - \OC::$server->getURLGenerator(), - \OC::$server->get(LoggerInterface::class), + Server::get(IURLGenerator::class), + Server::get(LoggerInterface::class), \OC::$SERVERROOT . '/config/', \OC::$SERVERROOT . '/resources/config/' ); } - public function dataDetectPath(): array { + public static function dataDetectPath(): array { return [ ['foo.txt', 'text/plain'], ['foo.png', 'image/png'], @@ -45,16 +47,16 @@ class DetectionTest extends \Test\TestCase { } /** - * @dataProvider dataDetectPath * * @param string $path * @param string $expected */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataDetectPath')] public function testDetectPath(string $path, string $expected): void { $this->assertEquals($expected, $this->detection->detectPath($path)); } - public function dataDetectContent(): array { + public static function dataDetectContent(): array { return [ ['/', 'httpd/unix-directory'], ['/data.tar.gz', 'application/gzip'], @@ -65,16 +67,16 @@ class DetectionTest extends \Test\TestCase { } /** - * @dataProvider dataDetectContent * * @param string $path * @param string $expected */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataDetectContent')] public function testDetectContent(string $path, string $expected): void { $this->assertEquals($expected, $this->detection->detectContent(\OC::$SERVERROOT . '/tests/data' . $path)); } - public function dataDetect(): array { + public static function dataDetect(): array { return [ ['/', 'httpd/unix-directory'], ['/data.tar.gz', 'application/gzip'], @@ -85,11 +87,11 @@ class DetectionTest extends \Test\TestCase { } /** - * @dataProvider dataDetect * * @param string $path * @param string $expected */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataDetect')] public function testDetect(string $path, string $expected): void { $this->assertEquals($expected, $this->detection->detect(\OC::$SERVERROOT . '/tests/data' . $path)); } @@ -100,7 +102,42 @@ class DetectionTest extends \Test\TestCase { $this->assertEquals($expected, $result); } - public function dataGetSecureMimeType(): array { + public static function dataMimeTypeCustom(): array { + return [ + ['123', 'foobar/123'], + ['a123', 'foobar/123'], + ['bar', 'foobar/bar'], + ]; + } + + /** + * + * @param string $ext + * @param string $mime + */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataMimeTypeCustom')] + public function testDetectMimeTypeCustom(string $ext, string $mime): void { + $confDir = sys_get_temp_dir(); + file_put_contents($confDir . '/mimetypemapping.dist.json', json_encode([])); + + /** @var IURLGenerator $urlGenerator */ + $urlGenerator = $this->getMockBuilder(IURLGenerator::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var LoggerInterface $logger */ + $logger = $this->createMock(LoggerInterface::class); + + // Create new mapping file + file_put_contents($confDir . '/mimetypemapping.dist.json', json_encode([$ext => [$mime]])); + + $detection = new Detection($urlGenerator, $logger, $confDir, $confDir); + $mappings = $detection->getAllMappings(); + $this->assertArrayHasKey($ext, $mappings); + $this->assertEquals($mime, $detection->detectPath('foo.' . $ext)); + } + + public static function dataGetSecureMimeType(): array { return [ ['image/svg+xml', 'text/plain'], ['image/png', 'image/png'], @@ -108,16 +145,16 @@ class DetectionTest extends \Test\TestCase { } /** - * @dataProvider dataGetSecureMimeType * * @param string $mimeType * @param string $expected */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetSecureMimeType')] public function testGetSecureMimeType(string $mimeType, string $expected): void { $this->assertEquals($expected, $this->detection->getSecureMimeType($mimeType)); } - public function testMimeTypeIcon() { + public function testMimeTypeIcon(): void { if (!class_exists('org\\bovigo\\vfs\\vfsStream')) { $this->markTestSkipped('Package vfsStream not installed'); } @@ -220,14 +257,16 @@ class DetectionTest extends \Test\TestCase { ->getMock(); //Only call the url generator once + $calls = [ + ['core', 'filetypes/my-type.png'], + ['core', 'filetypes/my.png'], + ]; $urlGenerator->expects($this->exactly(2)) ->method('imagePath') - ->withConsecutive( - [$this->equalTo('core'), $this->equalTo('filetypes/my-type.png')], - [$this->equalTo('core'), $this->equalTo('filetypes/my.png')] - ) ->willReturnCallback( - function ($appName, $file) { + function ($appName, $file) use (&$calls) { + $expected = array_shift($calls); + $this->assertEquals($expected, [$appName, $file]); if ($file === 'filetypes/my.png') { return 'my.svg'; } @@ -250,15 +289,17 @@ class DetectionTest extends \Test\TestCase { ->getMock(); //Only call the url generator once + $calls = [ + ['core', 'filetypes/foo-bar.png'], + ['core', 'filetypes/foo.png'], + ['core', 'filetypes/file.png'], + ]; $urlGenerator->expects($this->exactly(3)) ->method('imagePath') - ->withConsecutive( - [$this->equalTo('core'), $this->equalTo('filetypes/foo-bar.png')], - [$this->equalTo('core'), $this->equalTo('filetypes/foo.png')], - [$this->equalTo('core'), $this->equalTo('filetypes/file.png')] - ) ->willReturnCallback( - function ($appName, $file) { + function ($appName, $file) use (&$calls) { + $expected = array_shift($calls); + $this->assertEquals($expected, [$appName, $file]); if ($file === 'filetypes/file.png') { return 'file.svg'; } diff --git a/tests/lib/Files/Type/LoaderTest.php b/tests/lib/Files/Type/LoaderTest.php index cd2788bd208..44745a50dc0 100644 --- a/tests/lib/Files/Type/LoaderTest.php +++ b/tests/lib/Files/Type/LoaderTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -9,6 +10,7 @@ namespace Test\Files\Type; use OC\Files\Type\Loader; use OCP\IDBConnection; +use OCP\Server; use Test\TestCase; class LoaderTest extends TestCase { @@ -16,7 +18,7 @@ class LoaderTest extends TestCase { protected Loader $loader; protected function setUp(): void { - $this->db = \OC::$server->get(IDBConnection::class); + $this->db = Server::get(IDBConnection::class); $this->loader = new Loader($this->db); } @@ -30,7 +32,7 @@ class LoaderTest extends TestCase { } - public function testGetMimetype() { + public function testGetMimetype(): void { $qb = $this->db->getQueryBuilder(); $qb->insert('mimetypes') ->values([ @@ -46,13 +48,13 @@ class LoaderTest extends TestCase { $this->assertEquals('testing/mymimetype', $mimetype); } - public function testGetNonexistentMimetype() { + public function testGetNonexistentMimetype(): void { $this->assertFalse($this->loader->exists('testing/nonexistent')); // hopefully this ID doesn't exist $this->assertNull($this->loader->getMimetypeById(12345)); } - public function testStore() { + public function testStore(): void { $this->assertFalse($this->loader->exists('testing/mymimetype')); $mimetypeId = $this->loader->getId('testing/mymimetype'); @@ -70,7 +72,7 @@ class LoaderTest extends TestCase { $this->assertEquals($mimetypeId, $this->loader->getId('testing/mymimetype')); } - public function testStoreExists() { + public function testStoreExists(): void { $mimetypeId = $this->loader->getId('testing/mymimetype'); $mimetypeId2 = $this->loader->getId('testing/mymimetype'); diff --git a/tests/lib/Files/Utils/ScannerTest.php b/tests/lib/Files/Utils/ScannerTest.php index c3ba696ac5c..49399ef70a6 100644 --- a/tests/lib/Files/Utils/ScannerTest.php +++ b/tests/lib/Files/Utils/ScannerTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -10,20 +11,25 @@ namespace Test\Files\Utils; use OC\Files\Filesystem; use OC\Files\Mount\MountPoint; use OC\Files\Storage\Temporary; +use OC\Files\Utils\Scanner; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Config\IMountProvider; +use OCP\Files\Config\IMountProviderCollection; use OCP\Files\Storage\IStorageFactory; +use OCP\IDBConnection; use OCP\IUser; +use OCP\IUserManager; +use OCP\Server; use Psr\Log\LoggerInterface; -class TestScanner extends \OC\Files\Utils\Scanner { +class TestScanner extends Scanner { /** - * @var \OC\Files\Mount\MountPoint[] $mounts + * @var MountPoint[] $mounts */ private $mounts = []; /** - * @param \OC\Files\Mount\MountPoint $mount + * @param MountPoint $mount */ public function addMount($mount) { $this->mounts[] = $mount; @@ -51,17 +57,17 @@ class ScannerTest extends \Test\TestCase { parent::setUp(); $this->userBackend = new \Test\Util\User\Dummy(); - \OC::$server->getUserManager()->registerBackend($this->userBackend); + Server::get(IUserManager::class)->registerBackend($this->userBackend); $this->loginAsUser(); } protected function tearDown(): void { $this->logout(); - \OC::$server->getUserManager()->removeBackend($this->userBackend); + Server::get(IUserManager::class)->removeBackend($this->userBackend); parent::tearDown(); } - public function testReuseExistingRoot() { + public function testReuseExistingRoot(): void { $storage = new Temporary([]); $mount = new MountPoint($storage, ''); Filesystem::getMountManager()->addMount($mount); @@ -71,7 +77,7 @@ class ScannerTest extends \Test\TestCase { $storage->file_put_contents('foo.txt', 'qwerty'); $storage->file_put_contents('folder/bar.txt', 'qwerty'); - $scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), $this->createMock(IEventDispatcher::class), \OC::$server->get(LoggerInterface::class)); + $scanner = new TestScanner('', Server::get(IDBConnection::class), $this->createMock(IEventDispatcher::class), Server::get(LoggerInterface::class)); $scanner->addMount($mount); $scanner->scan(''); @@ -83,7 +89,7 @@ class ScannerTest extends \Test\TestCase { $this->assertEquals($oldRoot, $newRoot); } - public function testReuseExistingFile() { + public function testReuseExistingFile(): void { $storage = new Temporary([]); $mount = new MountPoint($storage, ''); Filesystem::getMountManager()->addMount($mount); @@ -93,7 +99,7 @@ class ScannerTest extends \Test\TestCase { $storage->file_put_contents('foo.txt', 'qwerty'); $storage->file_put_contents('folder/bar.txt', 'qwerty'); - $scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), $this->createMock(IEventDispatcher::class), \OC::$server->get(LoggerInterface::class)); + $scanner = new TestScanner('', Server::get(IDBConnection::class), $this->createMock(IEventDispatcher::class), Server::get(LoggerInterface::class)); $scanner->addMount($mount); $scanner->scan(''); @@ -105,7 +111,7 @@ class ScannerTest extends \Test\TestCase { $this->assertEquals($old, $new); } - public function testScanSubMount() { + public function testScanSubMount(): void { $uid = $this->getUniqueID(); $this->userBackend->createUser($uid, 'test'); @@ -124,24 +130,21 @@ class ScannerTest extends \Test\TestCase { } }); - \OC::$server->getMountProviderCollection()->registerProvider($mountProvider); + Server::get(IMountProviderCollection::class)->registerProvider($mountProvider); $cache = $storage->getCache(); $storage->mkdir('folder'); $storage->file_put_contents('foo.txt', 'qwerty'); $storage->file_put_contents('folder/bar.txt', 'qwerty'); - $scanner = new \OC\Files\Utils\Scanner($uid, \OC::$server->getDatabaseConnection(), \OC::$server->query(IEventDispatcher::class), \OC::$server->get(LoggerInterface::class)); + $scanner = new Scanner($uid, Server::get(IDBConnection::class), Server::get(IEventDispatcher::class), Server::get(LoggerInterface::class)); $this->assertFalse($cache->inCache('folder/bar.txt')); $scanner->scan('/' . $uid . '/files/foo'); $this->assertTrue($cache->inCache('folder/bar.txt')); } - /** - * @return array - */ - public function invalidPathProvider() { + public static function invalidPathProvider(): array { return [ [ '../', @@ -156,18 +159,18 @@ class ScannerTest extends \Test\TestCase { } /** - * @dataProvider invalidPathProvider * @param string $invalidPath */ - public function testInvalidPathScanning($invalidPath) { + #[\PHPUnit\Framework\Attributes\DataProvider('invalidPathProvider')] + public function testInvalidPathScanning($invalidPath): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Invalid path to scan'); - $scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), $this->createMock(IEventDispatcher::class), \OC::$server->get(LoggerInterface::class)); + $scanner = new TestScanner('', Server::get(IDBConnection::class), $this->createMock(IEventDispatcher::class), Server::get(LoggerInterface::class)); $scanner->scan($invalidPath); } - public function testPropagateEtag() { + public function testPropagateEtag(): void { $storage = new Temporary([]); $mount = new MountPoint($storage, ''); Filesystem::getMountManager()->addMount($mount); @@ -177,7 +180,7 @@ class ScannerTest extends \Test\TestCase { $storage->file_put_contents('folder/bar.txt', 'qwerty'); $storage->touch('folder/bar.txt', time() - 200); - $scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), $this->createMock(IEventDispatcher::class), \OC::$server->get(LoggerInterface::class)); + $scanner = new TestScanner('', Server::get(IDBConnection::class), $this->createMock(IEventDispatcher::class), Server::get(LoggerInterface::class)); $scanner->addMount($mount); $scanner->scan(''); @@ -191,7 +194,7 @@ class ScannerTest extends \Test\TestCase { $this->assertNotEquals($oldRoot->getEtag(), $newRoot->getEtag()); } - public function testShallow() { + public function testShallow(): void { $storage = new Temporary([]); $mount = new MountPoint($storage, ''); Filesystem::getMountManager()->addMount($mount); @@ -203,7 +206,7 @@ class ScannerTest extends \Test\TestCase { $storage->file_put_contents('folder/bar.txt', 'qwerty'); $storage->file_put_contents('folder/subfolder/foobar.txt', 'qwerty'); - $scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), $this->createMock(IEventDispatcher::class), \OC::$server->get(LoggerInterface::class)); + $scanner = new TestScanner('', Server::get(IDBConnection::class), $this->createMock(IEventDispatcher::class), Server::get(LoggerInterface::class)); $scanner->addMount($mount); $scanner->scan('', $recusive = false); diff --git a/tests/lib/Files/ViewTest.php b/tests/lib/Files/ViewTest.php index 43a25150eaf..ad27c3f798c 100644 --- a/tests/lib/Files/ViewTest.php +++ b/tests/lib/Files/ViewTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -7,6 +8,7 @@ namespace Test\Files; +use OC\Files\Cache\Scanner; use OC\Files\Cache\Watcher; use OC\Files\Filesystem; use OC\Files\Mount\MountPoint; @@ -16,49 +18,75 @@ use OC\Files\Storage\Storage; use OC\Files\Storage\Temporary; use OC\Files\View; use OC\Share20\ShareDisableChecker; +use OCA\Files_Trashbin\Trash\ITrashManager; use OCP\Cache\CappedMemoryCache; use OCP\Constants; use OCP\Files\Config\IMountProvider; +use OCP\Files\Config\IMountProviderCollection; +use OCP\Files\Config\IUserMountCache; use OCP\Files\FileInfo; +use OCP\Files\ForbiddenException; use OCP\Files\GenericFileException; +use OCP\Files\InvalidPathException; use OCP\Files\Mount\IMountManager; +use OCP\Files\NotFoundException; use OCP\Files\Storage\IStorage; +use OCP\Files\Storage\IStorageFactory; +use OCP\IConfig; use OCP\IDBConnection; +use OCP\IGroup; +use OCP\IGroupManager; +use OCP\ITempManager; +use OCP\IUser; +use OCP\IUserManager; use OCP\Lock\ILockingProvider; use OCP\Lock\LockedException; +use OCP\Server; use OCP\Share\IManager as IShareManager; use OCP\Share\IShare; use OCP\Util; +use PHPUnit\Framework\MockObject\MockObject; use Test\HookHelper; use Test\TestMoveableMountPoint; use Test\Traits\UserTrait; class TemporaryNoTouch extends Temporary { - public function touch($path, $mtime = null) { + public function touch(string $path, ?int $mtime = null): bool { return false; } } class TemporaryNoCross extends Temporary { - public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime = null) { + public function copyFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath, bool $preserveMtime = false): bool { return Common::copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime); } - public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) { + public function moveFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath): bool { return Common::moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); } } class TemporaryNoLocal extends Temporary { - public function instanceOfStorage($className) { - if ($className === '\OC\Files\Storage\Local') { + public function instanceOfStorage(string $class): bool { + if ($class === '\OC\Files\Storage\Local') { return false; } else { - return parent::instanceOfStorage($className); + return parent::instanceOfStorage($class); } } } +class TestEventHandler { + public function umount() { + } + public function post_umount() { + } + public function preCallback() { + } + public function postCallback() { + } +} + /** * Class ViewTest * @@ -70,7 +98,7 @@ class ViewTest extends \Test\TestCase { use UserTrait; /** - * @var \OC\Files\Storage\Storage[] $storages + * @var Storage[] $storages */ private $storages = []; @@ -80,28 +108,28 @@ class ViewTest extends \Test\TestCase { private $user; /** - * @var \OCP\IUser + * @var IUser */ private $userObject; /** - * @var \OCP\IGroup + * @var IGroup */ private $groupObject; - /** @var \OC\Files\Storage\Storage */ + /** @var Storage */ private $tempStorage; protected function setUp(): void { parent::setUp(); \OC_Hook::clear(); - \OC_User::clearBackends(); - \OC_User::useBackend(new \Test\Util\User\Dummy()); + Server::get(IUserManager::class)->clearBackends(); + Server::get(IUserManager::class)->registerBackend(new \Test\Util\User\Dummy()); //login - $userManager = \OC::$server->getUserManager(); - $groupManager = \OC::$server->getGroupManager(); + $userManager = Server::get(IUserManager::class); + $groupManager = Server::get(IGroupManager::class); $this->user = 'test'; $this->userObject = $userManager->createUser('test', 'test'); @@ -111,7 +139,7 @@ class ViewTest extends \Test\TestCase { self::loginAsUser($this->user); /** @var IMountManager $manager */ - $manager = \OC::$server->get(IMountManager::class); + $manager = Server::get(IMountManager::class); $manager->removeMount('/test'); $this->tempStorage = null; @@ -132,13 +160,13 @@ class ViewTest extends \Test\TestCase { self::logout(); /** @var SetupManager $setupManager */ - $setupManager = \OC::$server->get(SetupManager::class); + $setupManager = Server::get(SetupManager::class); $setupManager->setupRoot(); $this->userObject->delete(); $this->groupObject->delete(); - $mountProviderCollection = \OC::$server->getMountProviderCollection(); + $mountProviderCollection = Server::get(IMountProviderCollection::class); self::invokePrivate($mountProviderCollection, 'providers', [[]]); parent::tearDown(); @@ -147,7 +175,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testCacheAPI() { + public function testCacheAPI(): void { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $storage3 = $this->getTestStorage(); @@ -230,35 +258,43 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testGetPath() { + public function testGetPath(): void { + $user = $this->createMock(IUser::class); + $user->method('getUID') + ->willReturn('test'); $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $storage3 = $this->getTestStorage(); - Filesystem::mount($storage1, [], '/'); - Filesystem::mount($storage2, [], '/substorage'); - Filesystem::mount($storage3, [], '/folder/anotherstorage'); + Filesystem::mount($storage1, [], '/test/files'); + Filesystem::mount($storage2, [], '/test/files/substorage'); + Filesystem::mount($storage3, [], '/test/files/folder/anotherstorage'); - $rootView = new View(''); + $userMountCache = Server::get(IUserMountCache::class); + $userMountCache->registerMounts($user, [ + new MountPoint($storage1, '/test/files'), + new MountPoint($storage2, '/test/files/substorage'), + new MountPoint($storage3, '/test/files/folder/anotherstorage'), + ]); + + $rootView = new View('/test/files'); $cachedData = $rootView->getFileInfo('/foo.txt'); - /** @var int $id1 */ - $id1 = $cachedData['fileid']; + $id1 = $cachedData->getId(); $this->assertEquals('/foo.txt', $rootView->getPath($id1)); $cachedData = $rootView->getFileInfo('/substorage/foo.txt'); - /** @var int $id2 */ - $id2 = $cachedData['fileid']; + $id2 = $cachedData->getId(); $this->assertEquals('/substorage/foo.txt', $rootView->getPath($id2)); - $folderView = new View('/substorage'); + $folderView = new View('/test/files/substorage'); $this->assertEquals('/foo.txt', $folderView->getPath($id2)); } - public function testGetPathNotExisting() { - $this->expectException(\OCP\Files\NotFoundException::class); + public function testGetPathNotExisting(): void { + $this->expectException(NotFoundException::class); $storage1 = $this->getTestStorage(); Filesystem::mount($storage1, [], '/'); @@ -274,7 +310,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testMountPointOverwrite() { + public function testMountPointOverwrite(): void { $storage1 = $this->getTestStorage(false); $storage2 = $this->getTestStorage(); $storage1->mkdir('substorage'); @@ -286,21 +322,19 @@ class ViewTest extends \Test\TestCase { $this->assertCount(4, $folderContent); } - public function sharingDisabledPermissionProvider() { + public static function sharingDisabledPermissionProvider(): array { return [ ['no', '', true], ['yes', 'group1', false], ]; } - /** - * @dataProvider sharingDisabledPermissionProvider - */ - public function testRemoveSharePermissionWhenSharingDisabledForUser($excludeGroups, $excludeGroupsList, $expectedShareable) { + #[\PHPUnit\Framework\Attributes\DataProvider('sharingDisabledPermissionProvider')] + public function testRemoveSharePermissionWhenSharingDisabledForUser($excludeGroups, $excludeGroupsList, $expectedShareable): void { // Reset sharing disabled for users cache - self::invokePrivate(\OC::$server->get(ShareDisableChecker::class), 'sharingDisabledForUsersCache', [new CappedMemoryCache()]); + self::invokePrivate(Server::get(ShareDisableChecker::class), 'sharingDisabledForUsersCache', [new CappedMemoryCache()]); - $config = \OC::$server->getConfig(); + $config = Server::get(IConfig::class); $oldExcludeGroupsFlag = $config->getAppValue('core', 'shareapi_exclude_groups', 'no'); $oldExcludeGroupsList = $config->getAppValue('core', 'shareapi_exclude_groups_list', ''); $config->setAppValue('core', 'shareapi_exclude_groups', $excludeGroups); @@ -323,10 +357,10 @@ class ViewTest extends \Test\TestCase { $config->setAppValue('core', 'shareapi_exclude_groups_list', $oldExcludeGroupsList); // Reset sharing disabled for users cache - self::invokePrivate(\OC::$server->get(ShareDisableChecker::class), 'sharingDisabledForUsersCache', [new CappedMemoryCache()]); + self::invokePrivate(Server::get(ShareDisableChecker::class), 'sharingDisabledForUsersCache', [new CappedMemoryCache()]); } - public function testCacheIncompleteFolder() { + public function testCacheIncompleteFolder(): void { $storage1 = $this->getTestStorage(false); Filesystem::mount($storage1, [], '/incomplete'); $rootView = new View('/incomplete'); @@ -339,7 +373,7 @@ class ViewTest extends \Test\TestCase { $this->assertCount(1, $entries); } - public function testAutoScan() { + public function testAutoScan(): void { $storage1 = $this->getTestStorage(false); $storage2 = $this->getTestStorage(false); Filesystem::mount($storage1, [], '/'); @@ -360,7 +394,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testSearch() { + public function testSearch(): void { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $storage3 = $this->getTestStorage(); @@ -410,7 +444,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testWatcher() { + public function testWatcher(): void { $storage1 = $this->getTestStorage(); Filesystem::mount($storage1, [], '/'); $storage1->getWatcher()->setPolicy(Watcher::CHECK_ALWAYS); @@ -431,7 +465,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testCopyBetweenStorageNoCross() { + public function testCopyBetweenStorageNoCross(): void { $storage1 = $this->getTestStorage(true, TemporaryNoCross::class); $storage2 = $this->getTestStorage(true, TemporaryNoCross::class); $this->copyBetweenStorages($storage1, $storage2); @@ -440,7 +474,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testCopyBetweenStorageCross() { + public function testCopyBetweenStorageCross(): void { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $this->copyBetweenStorages($storage1, $storage2); @@ -449,7 +483,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testCopyBetweenStorageCrossNonLocal() { + public function testCopyBetweenStorageCrossNonLocal(): void { $storage1 = $this->getTestStorage(true, TemporaryNoLocal::class); $storage2 = $this->getTestStorage(true, TemporaryNoLocal::class); $this->copyBetweenStorages($storage1, $storage2); @@ -477,7 +511,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testMoveBetweenStorageNoCross() { + public function testMoveBetweenStorageNoCross(): void { $storage1 = $this->getTestStorage(true, TemporaryNoCross::class); $storage2 = $this->getTestStorage(true, TemporaryNoCross::class); $this->moveBetweenStorages($storage1, $storage2); @@ -486,7 +520,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testMoveBetweenStorageCross() { + public function testMoveBetweenStorageCross(): void { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $this->moveBetweenStorages($storage1, $storage2); @@ -495,17 +529,17 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testMoveBetweenStorageCrossNonLocal() { + public function testMoveBetweenStorageCrossNonLocal(): void { $storage1 = $this->getTestStorage(true, TemporaryNoLocal::class); $storage2 = $this->getTestStorage(true, TemporaryNoLocal::class); $this->moveBetweenStorages($storage1, $storage2); } public function moveBetweenStorages($storage1, $storage2) { - Filesystem::mount($storage1, [], '/'); - Filesystem::mount($storage2, [], '/substorage'); + Filesystem::mount($storage1, [], '/' . $this->user . '/'); + Filesystem::mount($storage2, [], '/' . $this->user . '/substorage'); - $rootView = new View(''); + $rootView = new View('/' . $this->user); $rootView->rename('foo.txt', 'substorage/folder/foo.txt'); $this->assertFalse($rootView->file_exists('foo.txt')); $this->assertTrue($rootView->file_exists('substorage/folder/foo.txt')); @@ -518,7 +552,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testUnlink() { + public function testUnlink(): void { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); Filesystem::mount($storage1, [], '/'); @@ -538,14 +572,12 @@ class ViewTest extends \Test\TestCase { $this->assertFalse($rootView->file_exists('substorage/bar.txt')); } - public function rmdirOrUnlinkDataProvider() { + public static function rmdirOrUnlinkDataProvider(): array { return [['rmdir'], ['unlink']]; } - /** - * @dataProvider rmdirOrUnlinkDataProvider - */ - public function testRmdir($method) { + #[\PHPUnit\Framework\Attributes\DataProvider('rmdirOrUnlinkDataProvider')] + public function testRmdir($method): void { $storage1 = $this->getTestStorage(); Filesystem::mount($storage1, [], '/'); @@ -564,7 +596,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testUnlinkRootMustFail() { + public function testUnlinkRootMustFail(): void { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); Filesystem::mount($storage1, [], '/'); @@ -583,7 +615,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testTouch() { + public function testTouch(): void { $storage = $this->getTestStorage(true, TemporaryNoTouch::class); Filesystem::mount($storage, [], '/'); @@ -607,7 +639,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testTouchFloat() { + public function testTouchFloat(): void { $storage = $this->getTestStorage(true, TemporaryNoTouch::class); Filesystem::mount($storage, [], '/'); @@ -624,7 +656,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testViewHooks() { + public function testViewHooks(): void { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $defaultRoot = Filesystem::getRoot(); @@ -649,7 +681,7 @@ class ViewTest extends \Test\TestCase { $this->hookPath = $params['path']; } - public function testSearchNotOutsideView() { + public function testSearchNotOutsideView(): void { $storage1 = $this->getTestStorage(); Filesystem::mount($storage1, [], '/'); $storage1->rename('folder', 'foo'); @@ -665,11 +697,11 @@ class ViewTest extends \Test\TestCase { /** * @param bool $scan * @param string $class - * @return \OC\Files\Storage\Storage + * @return Storage */ private function getTestStorage($scan = true, $class = Temporary::class) { /** - * @var \OC\Files\Storage\Storage $storage + * @var Storage $storage */ $storage = new $class([]); $textData = "dummy file data\n"; @@ -690,7 +722,7 @@ class ViewTest extends \Test\TestCase { /** * @medium */ - public function testViewHooksIfRootStartsTheSame() { + public function testViewHooksIfRootStartsTheSame(): void { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $defaultRoot = Filesystem::getRoot(); @@ -721,7 +753,7 @@ class ViewTest extends \Test\TestCase { $this->hookCreatePath = $params['path']; } - public function testEditNoCreateHook() { + public function testEditNoCreateHook(): void { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $defaultRoot = Filesystem::getRoot(); @@ -751,10 +783,8 @@ class ViewTest extends \Test\TestCase { \OC_Hook::clear('OC_Filesystem', 'post_write'); } - /** - * @dataProvider resolvePathTestProvider - */ - public function testResolvePath($expected, $pathToTest) { + #[\PHPUnit\Framework\Attributes\DataProvider('resolvePathTestProvider')] + public function testResolvePath($expected, $pathToTest): void { $storage1 = $this->getTestStorage(); Filesystem::mount($storage1, [], '/'); @@ -770,7 +800,7 @@ class ViewTest extends \Test\TestCase { $this->assertTrue($exists); } - public function resolvePathTestProvider() { + public static function resolvePathTestProvider(): array { return [ ['foo.txt', 'foo.txt'], ['foo.txt', '/foo.txt'], @@ -785,7 +815,7 @@ class ViewTest extends \Test\TestCase { ]; } - public function testUTF8Names() { + public function testUTF8Names(): void { $names = ['虚', '和知しゃ和で', 'regular ascii', 'sɨˈrɪlɪk', 'ѨѬ', 'أنا أحب القراءة كثيرا']; $storage = new Temporary([]); @@ -828,7 +858,7 @@ class ViewTest extends \Test\TestCase { * 1024 is the max path length in mac */ $folderName = 'abcdefghijklmnopqrstuvwxyz012345678901234567890123456789'; - $tmpdirLength = strlen(\OC::$server->getTempManager()->getTemporaryFolder()); + $tmpdirLength = strlen(Server::get(ITempManager::class)->getTemporaryFolder()); if (\OC_Util::runningOnMac()) { $depth = ((1024 - $tmpdirLength) / 57); } else { @@ -864,7 +894,7 @@ class ViewTest extends \Test\TestCase { } } - public function testTouchNotSupported() { + public function testTouchNotSupported(): void { $storage = new TemporaryNoTouch([]); $scanner = $storage->getScanner(); Filesystem::mount($storage, [], '/test/'); @@ -875,13 +905,13 @@ class ViewTest extends \Test\TestCase { $info = $view->getFileInfo('/test/test'); $view->touch('/test/test', $past); - $scanner->scanFile('test', \OC\Files\Cache\Scanner::REUSE_ETAG); + $scanner->scanFile('test', Scanner::REUSE_ETAG); $info2 = $view->getFileInfo('/test/test'); $this->assertSame($info['etag'], $info2['etag']); } - public function testWatcherEtagCrossStorage() { + public function testWatcherEtagCrossStorage(): void { $storage1 = new Temporary([]); $storage2 = new Temporary([]); $scanner1 = $storage1->getScanner(); @@ -913,29 +943,29 @@ class ViewTest extends \Test\TestCase { $this->assertNotEquals($newFolderInfo->getEtag(), $oldEtag); } - /** - * @dataProvider absolutePathProvider - */ - public function testGetAbsolutePath($expectedPath, $relativePath) { + #[\PHPUnit\Framework\Attributes\DataProvider('absolutePathProvider')] + public function testGetAbsolutePath($expectedPath, $relativePath): void { $view = new View('/files'); $this->assertEquals($expectedPath, $view->getAbsolutePath($relativePath)); } - public function testPartFileInfo() { + public function testPartFileInfo(): void { $storage = new Temporary([]); $scanner = $storage->getScanner(); Filesystem::mount($storage, [], '/test/'); - $storage->file_put_contents('test.part', 'foobar'); + $sizeWritten = $storage->file_put_contents('test.part', 'foobar'); $scanner->scan(''); $view = new View('/test'); $info = $view->getFileInfo('test.part'); $this->assertInstanceOf('\OCP\Files\FileInfo', $info); $this->assertNull($info->getId()); + $this->assertEquals(6, $sizeWritten); $this->assertEquals(6, $info->getSize()); + $this->assertEquals('foobar', $view->file_get_contents('test.part')); } - public function absolutePathProvider() { + public static function absolutePathProvider(): array { return [ ['/files/', ''], ['/files/0', '0'], @@ -947,32 +977,28 @@ class ViewTest extends \Test\TestCase { ]; } - /** - * @dataProvider chrootRelativePathProvider - */ - public function testChrootGetRelativePath($root, $absolutePath, $expectedPath) { + #[\PHPUnit\Framework\Attributes\DataProvider('chrootRelativePathProvider')] + public function testChrootGetRelativePath($root, $absolutePath, $expectedPath): void { $view = new View('/files'); $view->chroot($root); $this->assertEquals($expectedPath, $view->getRelativePath($absolutePath)); } - public function chrootRelativePathProvider() { - return $this->relativePathProvider('/'); + public static function chrootRelativePathProvider(): array { + return self::relativePathProvider('/'); } - /** - * @dataProvider initRelativePathProvider - */ - public function testInitGetRelativePath($root, $absolutePath, $expectedPath) { + #[\PHPUnit\Framework\Attributes\DataProvider('initRelativePathProvider')] + public function testInitGetRelativePath($root, $absolutePath, $expectedPath): void { $view = new View($root); $this->assertEquals($expectedPath, $view->getRelativePath($absolutePath)); } - public function initRelativePathProvider() { - return $this->relativePathProvider(null); + public static function initRelativePathProvider(): array { + return self::relativePathProvider(null); } - public function relativePathProvider($missingRootExpectedPath) { + public static function relativePathProvider($missingRootExpectedPath): array { return [ // No root - returns the path ['', '/files', '/files'], @@ -1043,7 +1069,7 @@ class ViewTest extends \Test\TestCase { ]; } - public function testFileView() { + public function testFileView(): void { $storage = new Temporary([]); $scanner = $storage->getScanner(); $storage->file_put_contents('foo.txt', 'bar'); @@ -1059,11 +1085,9 @@ class ViewTest extends \Test\TestCase { $this->assertEquals('foo', $view->file_get_contents('')); } - /** - * @dataProvider tooLongPathDataProvider - */ - public function testTooLongPath($operation, $param0 = null) { - $this->expectException(\OCP\Files\InvalidPathException::class); + #[\PHPUnit\Framework\Attributes\DataProvider('tooLongPathDataProvider')] + public function testTooLongPath($operation, $param0 = null): void { + $this->expectException(InvalidPathException::class); $longPath = ''; @@ -1092,7 +1116,7 @@ class ViewTest extends \Test\TestCase { call_user_func([$rootView, $operation], $longPath, $param0); } - public function tooLongPathDataProvider() { + public static function tooLongPathDataProvider(): array { return [ ['getAbsolutePath'], ['getRelativePath'], @@ -1137,7 +1161,7 @@ class ViewTest extends \Test\TestCase { ]; } - public function testRenameCrossStoragePreserveMtime() { + public function testRenameCrossStoragePreserveMtime(): void { $storage1 = new Temporary([]); $storage2 = new Temporary([]); $storage1->mkdir('sub'); @@ -1162,11 +1186,11 @@ class ViewTest extends \Test\TestCase { $this->assertEquals($time, $view->filemtime('/test/sub/storage/foo/bar.txt')); } - public function testRenameFailDeleteTargetKeepSource() { + public function testRenameFailDeleteTargetKeepSource(): void { $this->doTestCopyRenameFail('rename'); } - public function testCopyFailDeleteTargetKeepSource() { + public function testCopyFailDeleteTargetKeepSource(): void { $this->doTestCopyRenameFail('copy'); } @@ -1175,11 +1199,11 @@ class ViewTest extends \Test\TestCase { /** @var \PHPUnit\Framework\MockObject\MockObject|Temporary $storage2 */ $storage2 = $this->getMockBuilder(TemporaryNoCross::class) ->setConstructorArgs([[]]) - ->setMethods(['fopen', 'writeStream']) + ->onlyMethods(['fopen', 'writeStream']) ->getMock(); $storage2->method('writeStream') - ->willThrowException(new GenericFileException("Failed to copy stream")); + ->willThrowException(new GenericFileException('Failed to copy stream')); $storage1->mkdir('sub'); $storage1->file_put_contents('foo.txt', '0123456789ABCDEFGH'); @@ -1217,11 +1241,11 @@ class ViewTest extends \Test\TestCase { $this->assertFalse($storage2->getCache()->get('dirtomove/indir2.txt')); } - public function testDeleteFailKeepCache() { + public function testDeleteFailKeepCache(): void { /** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->getMockBuilder(Temporary::class) ->setConstructorArgs([[]]) - ->setMethods(['unlink']) + ->onlyMethods(['unlink']) ->getMock(); $storage->expects($this->once()) ->method('unlink') @@ -1238,7 +1262,7 @@ class ViewTest extends \Test\TestCase { $this->assertTrue($cache->inCache('foo.txt')); } - public function directoryTraversalProvider() { + public static function directoryTraversalProvider(): array { return [ ['../test/'], ['..\\test\\my/../folder'], @@ -1247,16 +1271,16 @@ class ViewTest extends \Test\TestCase { } /** - * @dataProvider directoryTraversalProvider * @param string $root */ - public function testConstructDirectoryTraversalException($root) { + #[\PHPUnit\Framework\Attributes\DataProvider('directoryTraversalProvider')] + public function testConstructDirectoryTraversalException($root): void { $this->expectException(\Exception::class); new View($root); } - public function testRenameOverWrite() { + public function testRenameOverWrite(): void { $storage = new Temporary([]); $scanner = $storage->getScanner(); $storage->mkdir('sub'); @@ -1269,35 +1293,35 @@ class ViewTest extends \Test\TestCase { $this->assertTrue($view->rename('/test/foo.txt', '/test/foo/bar.txt')); } - public function testSetMountOptionsInStorage() { + public function testSetMountOptionsInStorage(): void { $mount = new MountPoint(Temporary::class, '/asd/', [[]], Filesystem::getLoader(), ['foo' => 'bar']); Filesystem::getMountManager()->addMount($mount); - /** @var \OC\Files\Storage\Common $storage */ + /** @var Common $storage */ $storage = $mount->getStorage(); $this->assertEquals($storage->getMountOption('foo'), 'bar'); } - public function testSetMountOptionsWatcherPolicy() { + public function testSetMountOptionsWatcherPolicy(): void { $mount = new MountPoint(Temporary::class, '/asd/', [[]], Filesystem::getLoader(), ['filesystem_check_changes' => Watcher::CHECK_NEVER]); Filesystem::getMountManager()->addMount($mount); - /** @var \OC\Files\Storage\Common $storage */ + /** @var Common $storage */ $storage = $mount->getStorage(); $watcher = $storage->getWatcher(); $this->assertEquals(Watcher::CHECK_NEVER, $watcher->getPolicy()); } - public function testGetAbsolutePathOnNull() { + public function testGetAbsolutePathOnNull(): void { $view = new View(); $this->assertNull($view->getAbsolutePath(null)); } - public function testGetRelativePathOnNull() { + public function testGetRelativePathOnNull(): void { $view = new View(); $this->assertNull($view->getRelativePath(null)); } - public function testNullAsRoot() { + public function testNullAsRoot(): void { $this->expectException(\TypeError::class); new View(null); @@ -1307,13 +1331,13 @@ class ViewTest extends \Test\TestCase { * e.g. reading from a folder that's being renamed * * - * @dataProvider dataLockPaths * * @param string $rootPath * @param string $pathPrefix */ - public function testReadFromWriteLockedPath($rootPath, $pathPrefix) { - $this->expectException(\OCP\Lock\LockedException::class); + #[\PHPUnit\Framework\Attributes\DataProvider('dataLockPaths')] + public function testReadFromWriteLockedPath($rootPath, $pathPrefix): void { + $this->expectException(LockedException::class); $rootPath = str_replace('{folder}', 'files', $rootPath); $pathPrefix = str_replace('{folder}', 'files', $pathPrefix); @@ -1328,12 +1352,12 @@ class ViewTest extends \Test\TestCase { /** * Reading from a files_encryption folder that's being renamed * - * @dataProvider dataLockPaths * * @param string $rootPath * @param string $pathPrefix */ - public function testReadFromWriteUnlockablePath($rootPath, $pathPrefix) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataLockPaths')] + public function testReadFromWriteUnlockablePath($rootPath, $pathPrefix): void { $rootPath = str_replace('{folder}', 'files_encryption', $rootPath); $pathPrefix = str_replace('{folder}', 'files_encryption', $pathPrefix); @@ -1348,13 +1372,13 @@ class ViewTest extends \Test\TestCase { * e.g. writing a file that's being downloaded * * - * @dataProvider dataLockPaths * * @param string $rootPath * @param string $pathPrefix */ - public function testWriteToReadLockedFile($rootPath, $pathPrefix) { - $this->expectException(\OCP\Lock\LockedException::class); + #[\PHPUnit\Framework\Attributes\DataProvider('dataLockPaths')] + public function testWriteToReadLockedFile($rootPath, $pathPrefix): void { + $this->expectException(LockedException::class); $rootPath = str_replace('{folder}', 'files', $rootPath); $pathPrefix = str_replace('{folder}', 'files', $pathPrefix); @@ -1369,12 +1393,12 @@ class ViewTest extends \Test\TestCase { /** * Writing a file that's being downloaded * - * @dataProvider dataLockPaths * * @param string $rootPath * @param string $pathPrefix */ - public function testWriteToReadUnlockableFile($rootPath, $pathPrefix) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataLockPaths')] + public function testWriteToReadUnlockableFile($rootPath, $pathPrefix): void { $rootPath = str_replace('{folder}', 'files_encryption', $rootPath); $pathPrefix = str_replace('{folder}', 'files_encryption', $pathPrefix); @@ -1388,8 +1412,8 @@ class ViewTest extends \Test\TestCase { /** * Test that locks are on mount point paths instead of mount root */ - public function testLockLocalMountPointPathInsteadOfStorageRoot() { - $lockingProvider = \OC::$server->get(ILockingProvider::class); + public function testLockLocalMountPointPathInsteadOfStorageRoot(): void { + $lockingProvider = Server::get(ILockingProvider::class); $view = new View('/testuser/files/'); $storage = new Temporary([]); Filesystem::mount($storage, [], '/'); @@ -1418,8 +1442,8 @@ class ViewTest extends \Test\TestCase { /** * Test that locks are on mount point paths and also mount root when requested */ - public function testLockStorageRootButNotLocalMountPoint() { - $lockingProvider = \OC::$server->get(ILockingProvider::class); + public function testLockStorageRootButNotLocalMountPoint(): void { + $lockingProvider = Server::get(ILockingProvider::class); $view = new View('/testuser/files/'); $storage = new Temporary([]); Filesystem::mount($storage, [], '/'); @@ -1448,8 +1472,8 @@ class ViewTest extends \Test\TestCase { /** * Test that locks are on mount point paths and also mount root when requested */ - public function testLockMountPointPathFailReleasesBoth() { - $lockingProvider = \OC::$server->get(ILockingProvider::class); + public function testLockMountPointPathFailReleasesBoth(): void { + $lockingProvider = Server::get(ILockingProvider::class); $view = new View('/testuser/files/'); $storage = new Temporary([]); Filesystem::mount($storage, [], '/'); @@ -1476,7 +1500,7 @@ class ViewTest extends \Test\TestCase { $lockingProvider->releaseAll(); } - public function dataLockPaths() { + public static function dataLockPaths(): array { return [ ['/testuser/{folder}', ''], ['/testuser', '/{folder}'], @@ -1484,7 +1508,7 @@ class ViewTest extends \Test\TestCase { ]; } - public function pathRelativeToFilesProvider() { + public static function pathRelativeToFilesProvider(): array { return [ ['admin/files', ''], ['admin/files/x', 'x'], @@ -1496,15 +1520,13 @@ class ViewTest extends \Test\TestCase { ]; } - /** - * @dataProvider pathRelativeToFilesProvider - */ - public function testGetPathRelativeToFiles($path, $expectedPath) { + #[\PHPUnit\Framework\Attributes\DataProvider('pathRelativeToFilesProvider')] + public function testGetPathRelativeToFiles($path, $expectedPath): void { $view = new View(); $this->assertEquals($expectedPath, $view->getPathRelativeToFiles($path)); } - public function pathRelativeToFilesProviderExceptionCases() { + public static function pathRelativeToFilesProviderExceptionCases(): array { return [ [''], ['x'], @@ -1515,10 +1537,10 @@ class ViewTest extends \Test\TestCase { } /** - * @dataProvider pathRelativeToFilesProviderExceptionCases * @param string $path */ - public function testGetPathRelativeToFilesWithInvalidArgument($path) { + #[\PHPUnit\Framework\Attributes\DataProvider('pathRelativeToFilesProviderExceptionCases')] + public function testGetPathRelativeToFilesWithInvalidArgument($path): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('$absolutePath must be relative to "files"'); @@ -1526,7 +1548,7 @@ class ViewTest extends \Test\TestCase { $view->getPathRelativeToFiles($path); } - public function testChangeLock() { + public function testChangeLock(): void { $view = new View('/testuser/files/'); $storage = new Temporary([]); Filesystem::mount($storage, [], '/'); @@ -1547,7 +1569,7 @@ class ViewTest extends \Test\TestCase { $this->assertFalse($this->isFileLocked($view, '/test//sub', ILockingProvider::LOCK_EXCLUSIVE)); } - public function hookPathProvider() { + public static function hookPathProvider(): array { return [ ['/foo/files', '/foo', true], ['/foo/files/bar', '/foo', true], @@ -1560,12 +1582,12 @@ class ViewTest extends \Test\TestCase { } /** - * @dataProvider hookPathProvider * @param $root * @param $path * @param $shouldEmit */ - public function testHookPaths($root, $path, $shouldEmit) { + #[\PHPUnit\Framework\Attributes\DataProvider('hookPathProvider')] + public function testHookPaths($root, $path, $shouldEmit): void { $filesystemReflection = new \ReflectionClass(Filesystem::class); $defaultRootValue = $filesystemReflection->getProperty('defaultInstance'); $defaultRootValue->setAccessible(true); @@ -1588,16 +1610,15 @@ class ViewTest extends \Test\TestCase { $mounts = []; foreach ($mountPoints as $mountPoint) { $storage = $this->getMockBuilder(Storage::class) - ->setMethods([]) - ->setConstructorArgs([[]]) + ->onlyMethods([]) ->getMock(); $storage->method('getId')->willReturn('non-null-id'); $storage->method('getStorageCache')->willReturnCallback(function () use ($storage) { - return new \OC\Files\Cache\Storage($storage, true, \OC::$server->get(IDBConnection::class)); + return new \OC\Files\Cache\Storage($storage, true, Server::get(IDBConnection::class)); }); $mounts[] = $this->getMockBuilder(TestMoveableMountPoint::class) - ->setMethods(['moveMount']) + ->onlyMethods(['moveMount']) ->setConstructorArgs([$storage, $mountPoint]) ->getMock(); } @@ -1608,7 +1629,7 @@ class ViewTest extends \Test\TestCase { ->method('getMountsForUser') ->willReturn($mounts); - $mountProviderCollection = \OC::$server->getMountProviderCollection(); + $mountProviderCollection = Server::get(IMountProviderCollection::class); $mountProviderCollection->registerProvider($mountProvider); return $mounts; @@ -1617,7 +1638,7 @@ class ViewTest extends \Test\TestCase { /** * Test mount point move */ - public function testMountPointMove() { + public function testMountPointMove(): void { self::loginAsUser($this->user); [$mount1, $mount2] = $this->createTestMovableMountPoints([ @@ -1639,10 +1660,27 @@ class ViewTest extends \Test\TestCase { $this->assertTrue($view->rename('mount2', 'sub/moved_mount'), 'Can move a mount point into a subdirectory'); } - /** - * Test that moving a mount point into another is forbidden - */ - public function testMoveMountPointIntoAnother() { + public function testMoveMountPointOverwrite(): void { + self::loginAsUser($this->user); + + [$mount1, $mount2] = $this->createTestMovableMountPoints([ + $this->user . '/files/mount1', + $this->user . '/files/mount2', + ]); + + $mount1->expects($this->never()) + ->method('moveMount'); + + $mount2->expects($this->never()) + ->method('moveMount'); + + $view = new View('/' . $this->user . '/files/'); + + $this->expectException(ForbiddenException::class); + $view->rename('mount1', 'mount2'); + } + + public function testMoveMountPointIntoMount(): void { self::loginAsUser($this->user); [$mount1, $mount2] = $this->createTestMovableMountPoints([ @@ -1658,51 +1696,74 @@ class ViewTest extends \Test\TestCase { $view = new View('/' . $this->user . '/files/'); - $this->assertFalse($view->rename('mount1', 'mount2'), 'Cannot overwrite another mount point'); - $this->assertFalse($view->rename('mount1', 'mount2/sub'), 'Cannot move a mount point into another'); + $this->expectException(ForbiddenException::class); + $view->rename('mount1', 'mount2/sub'); } /** * Test that moving a mount point into a shared folder is forbidden */ - public function testMoveMountPointIntoSharedFolder() { + public function testMoveMountPointIntoSharedFolder(): void { self::loginAsUser($this->user); - [$mount1] = $this->createTestMovableMountPoints([ + [$mount1, $mount2] = $this->createTestMovableMountPoints([ $this->user . '/files/mount1', + $this->user . '/files/mount2', ]); $mount1->expects($this->never()) ->method('moveMount'); + $mount2->expects($this->once()) + ->method('moveMount') + ->willReturn(true); + $view = new View('/' . $this->user . '/files/'); $view->mkdir('shareddir'); $view->mkdir('shareddir/sub'); $view->mkdir('shareddir/sub2'); + // Create a similar named but non-shared folder + $view->mkdir('shareddir notshared'); $fileId = $view->getFileInfo('shareddir')->getId(); - $userObject = \OC::$server->getUserManager()->createUser('test2', 'IHateNonMockableStaticClasses'); + $userObject = Server::get(IUserManager::class)->createUser('test2', 'IHateNonMockableStaticClasses'); $userFolder = \OC::$server->getUserFolder($this->user); $shareDir = $userFolder->get('shareddir'); - $shareManager = \OC::$server->get(IShareManager::class); + $shareManager = Server::get(IShareManager::class); $share = $shareManager->newShare(); $share->setSharedWith('test2') ->setSharedBy($this->user) ->setShareType(IShare::TYPE_USER) - ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setPermissions(Constants::PERMISSION_READ) ->setNode($shareDir); $shareManager->createShare($share); - $this->assertFalse($view->rename('mount1', 'shareddir'), 'Cannot overwrite shared folder'); - $this->assertFalse($view->rename('mount1', 'shareddir/sub'), 'Cannot move mount point into shared folder'); - $this->assertFalse($view->rename('mount1', 'shareddir/sub/sub2'), 'Cannot move mount point into shared subfolder'); + try { + $view->rename('mount1', 'shareddir'); + $this->fail('Cannot overwrite shared folder'); + } catch (ForbiddenException $e) { + + } + try { + $view->rename('mount1', 'shareddir/sub'); + $this->fail('Cannot move mount point into shared folder'); + } catch (ForbiddenException $e) { + + } + try { + $view->rename('mount1', 'shareddir/sub/sub2'); + $this->fail('Cannot move mount point into shared subfolder'); + } catch (ForbiddenException $e) { + + } + $this->assertTrue($view->rename('mount2', 'shareddir notshared/sub'), 'Can move mount point into a similarly named but non-shared folder'); $shareManager->deleteShare($share); $userObject->delete(); } - public function basicOperationProviderForLocks() { + public static function basicOperationProviderForLocks(): array { return [ // --- write hook ---- [ @@ -1742,6 +1803,8 @@ class ViewTest extends \Test\TestCase { ILockingProvider::LOCK_SHARED, ILockingProvider::LOCK_EXCLUSIVE, ILockingProvider::LOCK_SHARED, + null, + 0, ], // ---- delete hook ---- @@ -1773,6 +1836,8 @@ class ViewTest extends \Test\TestCase { ILockingProvider::LOCK_SHARED, ILockingProvider::LOCK_SHARED, null, + null, + false, ], [ 'fopen', @@ -1799,8 +1864,28 @@ class ViewTest extends \Test\TestCase { // ---- no hooks, no locks --- ['is_dir', ['dir'], 'dir', null], ['is_file', ['dir'], 'dir', null], - ['stat', ['dir'], 'dir', null], - ['filetype', ['dir'], 'dir', null], + [ + 'stat', + ['dir'], + 'dir', + null, + ILockingProvider::LOCK_SHARED, + ILockingProvider::LOCK_SHARED, + ILockingProvider::LOCK_SHARED, + null, + false, + ], + [ + 'filetype', + ['dir'], + 'dir', + null, + ILockingProvider::LOCK_SHARED, + ILockingProvider::LOCK_SHARED, + ILockingProvider::LOCK_SHARED, + null, + false, + ], [ 'filesize', ['dir'], @@ -1819,14 +1904,23 @@ class ViewTest extends \Test\TestCase { ['isDeletable', ['dir'], 'dir', null], ['isSharable', ['dir'], 'dir', null], ['file_exists', ['dir'], 'dir', null], - ['filemtime', ['dir'], 'dir', null], + [ + 'filemtime', + ['dir'], + 'dir', + null, + ILockingProvider::LOCK_SHARED, + ILockingProvider::LOCK_SHARED, + ILockingProvider::LOCK_SHARED, + null, + false, + ], ]; } /** * Test whether locks are set before and after the operation * - * @dataProvider basicOperationProviderForLocks * * @param string $operation operation name on the view * @param array $operationArgs arguments for the operation @@ -1836,8 +1930,9 @@ class ViewTest extends \Test\TestCase { * @param int $expectedLockDuring expected lock during operation * @param int $expectedLockAfter expected lock during post hooks * @param int $expectedStrayLock expected lock after returning, should - * be null (unlock) for most operations + * be null (unlock) for most operations */ + #[\PHPUnit\Framework\Attributes\DataProvider('basicOperationProviderForLocks')] public function testLockBasicOperation( $operation, $operationArgs, @@ -1848,14 +1943,19 @@ class ViewTest extends \Test\TestCase { $expectedLockAfter = ILockingProvider::LOCK_SHARED, $expectedStrayLock = null, $returnValue = true, - ) { + ): void { $view = new View('/' . $this->user . '/files/'); - /** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */ + /** @var Temporary&MockObject $storage */ $storage = $this->getMockBuilder(Temporary::class) - ->setMethods([$operation]) + ->onlyMethods([$operation]) ->getMock(); + /* Pause trash to avoid the trashbin intercepting rmdir and unlink calls */ + Server::get(ITrashManager::class)->pauseTrash(); + /* Same thing with encryption wrapper */ + Server::get(IStorageFactory::class)->removeStorageWrapper('oc_encryption'); + Filesystem::mount($storage, [], $this->user . '/'); // work directly on disk because mkdir might be mocked @@ -1891,19 +1991,22 @@ class ViewTest extends \Test\TestCase { } $this->assertEquals($expectedStrayLock, $this->getFileLockType($view, $lockedPath)); + + /* Resume trash to avoid side effects */ + Server::get(ITrashManager::class)->resumeTrash(); } /** * Test locks for file_put_content with stream. * This code path uses $storage->fopen instead */ - public function testLockFilePutContentWithStream() { + public function testLockFilePutContentWithStream(): void { $view = new View('/' . $this->user . '/files/'); $path = 'test_file_put_contents.txt'; /** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->getMockBuilder(Temporary::class) - ->setMethods(['fopen']) + ->onlyMethods(['fopen']) ->getMock(); Filesystem::mount($storage, [], $this->user . '/'); @@ -1936,13 +2039,13 @@ class ViewTest extends \Test\TestCase { /** * Test locks for fopen with fclose at the end */ - public function testLockFopen() { + public function testLockFopen(): void { $view = new View('/' . $this->user . '/files/'); $path = 'test_file_put_contents.txt'; /** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->getMockBuilder(Temporary::class) - ->setMethods(['fopen']) + ->onlyMethods(['fopen']) ->getMock(); Filesystem::mount($storage, [], $this->user . '/'); @@ -1979,27 +2082,32 @@ class ViewTest extends \Test\TestCase { /** * Test locks for fopen with fclose at the end * - * @dataProvider basicOperationProviderForLocks * * @param string $operation operation name on the view * @param array $operationArgs arguments for the operation * @param string $path path of the locked item to check */ + #[\PHPUnit\Framework\Attributes\DataProvider('basicOperationProviderForLocks')] public function testLockBasicOperationUnlocksAfterException( $operation, $operationArgs, - $path - ) { + $path, + ): void { if ($operation === 'touch') { - $this->markTestSkipped("touch handles storage exceptions internally"); + $this->markTestSkipped('touch handles storage exceptions internally'); } $view = new View('/' . $this->user . '/files/'); /** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->getMockBuilder(Temporary::class) - ->setMethods([$operation]) + ->onlyMethods([$operation]) ->getMock(); + /* Pause trash to avoid the trashbin intercepting rmdir and unlink calls */ + Server::get(ITrashManager::class)->pauseTrash(); + /* Same thing with encryption wrapper */ + Server::get(IStorageFactory::class)->removeStorageWrapper('oc_encryption'); + Filesystem::mount($storage, [], $this->user . '/'); // work directly on disk because mkdir might be mocked @@ -2012,7 +2120,7 @@ class ViewTest extends \Test\TestCase { $storage->expects($this->once()) ->method($operation) ->willReturnCallback( - function () { + function (): void { throw new \Exception('Simulated exception'); } ); @@ -2026,9 +2134,12 @@ class ViewTest extends \Test\TestCase { } $this->assertTrue($thrown, 'Exception was rethrown'); $this->assertNull($this->getFileLockType($view, $path), 'File got unlocked after exception'); + + /* Resume trash to avoid side effects */ + Server::get(ITrashManager::class)->resumeTrash(); } - public function testLockBasicOperationUnlocksAfterLockException() { + public function testLockBasicOperationUnlocksAfterLockException(): void { $view = new View('/' . $this->user . '/files/'); $storage = new Temporary([]); @@ -2062,24 +2173,24 @@ class ViewTest extends \Test\TestCase { /** * Test locks for fopen with fclose at the end * - * @dataProvider basicOperationProviderForLocks * * @param string $operation operation name on the view * @param array $operationArgs arguments for the operation * @param string $path path of the locked item to check * @param string $hookType hook type */ + #[\PHPUnit\Framework\Attributes\DataProvider('basicOperationProviderForLocks')] public function testLockBasicOperationUnlocksAfterCancelledHook( $operation, $operationArgs, $path, - $hookType - ) { + $hookType, + ): void { $view = new View('/' . $this->user . '/files/'); /** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->getMockBuilder(Temporary::class) - ->setMethods([$operation]) + ->onlyMethods([$operation]) ->getMock(); Filesystem::mount($storage, [], $this->user . '/'); @@ -2097,7 +2208,7 @@ class ViewTest extends \Test\TestCase { $this->assertNull($this->getFileLockType($view, $path), 'File got unlocked after exception'); } - public function lockFileRenameOrCopyDataProvider() { + public static function lockFileRenameOrCopyDataProvider(): array { return [ ['rename', ILockingProvider::LOCK_EXCLUSIVE], ['copy', ILockingProvider::LOCK_SHARED], @@ -2107,29 +2218,29 @@ class ViewTest extends \Test\TestCase { /** * Test locks for rename or copy operation * - * @dataProvider lockFileRenameOrCopyDataProvider * * @param string $operation operation to be done on the view * @param int $expectedLockTypeSourceDuring expected lock type on source file during - * the operation + * the operation */ - public function testLockFileRename($operation, $expectedLockTypeSourceDuring) { + #[\PHPUnit\Framework\Attributes\DataProvider('lockFileRenameOrCopyDataProvider')] + public function testLockFileRename($operation, $expectedLockTypeSourceDuring): void { $view = new View('/' . $this->user . '/files/'); /** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->getMockBuilder(Temporary::class) - ->setMethods([$operation, 'getMetaData', 'filemtime']) + ->onlyMethods([$operation, 'getMetaData', 'filemtime']) ->getMock(); $storage->expects($this->any()) ->method('getMetaData') - ->will($this->returnValue([ + ->willReturn([ 'mtime' => 1885434487, 'etag' => '', 'mimetype' => 'text/plain', 'permissions' => Constants::PERMISSION_ALL, 'size' => 3 - ])); + ]); $storage->expects($this->any()) ->method('filemtime') ->willReturn(123456789); @@ -2137,6 +2248,9 @@ class ViewTest extends \Test\TestCase { $sourcePath = 'original.txt'; $targetPath = 'target.txt'; + /* Disable encryption wrapper to avoid it intercepting mocked call */ + Server::get(IStorageFactory::class)->removeStorageWrapper('oc_encryption'); + Filesystem::mount($storage, [], $this->user . '/'); $storage->mkdir('files'); $view->file_put_contents($sourcePath, 'meh'); @@ -2177,19 +2291,22 @@ class ViewTest extends \Test\TestCase { * We expect that we catch the exception, free the lock and re-throw it. * */ - public function testLockFileCopyException() { + public function testLockFileCopyException(): void { $this->expectException(\Exception::class); $view = new View('/' . $this->user . '/files/'); /** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->getMockBuilder(Temporary::class) - ->setMethods(['copy']) + ->onlyMethods(['copy']) ->getMock(); $sourcePath = 'original.txt'; $targetPath = 'target.txt'; + /* Disable encryption wrapper to avoid it intercepting mocked call */ + Server::get(IStorageFactory::class)->removeStorageWrapper('oc_encryption'); + Filesystem::mount($storage, [], $this->user . '/'); $storage->mkdir('files'); $view->file_put_contents($sourcePath, 'meh'); @@ -2197,7 +2314,7 @@ class ViewTest extends \Test\TestCase { $storage->expects($this->once()) ->method('copy') ->willReturnCallback( - function () { + function (): void { throw new \Exception(); } ); @@ -2220,7 +2337,7 @@ class ViewTest extends \Test\TestCase { /** * Test rename operation: unlock first path when second path was locked */ - public function testLockFileRenameUnlockOnException() { + public function testLockFileRenameUnlockOnException(): void { self::loginAsUser('test'); $view = new View('/' . $this->user . '/files/'); @@ -2253,7 +2370,7 @@ class ViewTest extends \Test\TestCase { /** * Test rename operation: unlock first path when second path was locked */ - public function testGetOwner() { + public function testGetOwner(): void { self::loginAsUser('test'); $view = new View('/test/files/'); @@ -2281,7 +2398,7 @@ class ViewTest extends \Test\TestCase { $this->assertEquals('test', $folderInfo[0]->getOwner()->getUID()); } - public function lockFileRenameOrCopyCrossStorageDataProvider() { + public static function lockFileRenameOrCopyCrossStorageDataProvider(): array { return [ ['rename', 'moveFromStorage', ILockingProvider::LOCK_EXCLUSIVE], ['copy', 'copyFromStorage', ILockingProvider::LOCK_SHARED], @@ -2291,34 +2408,34 @@ class ViewTest extends \Test\TestCase { /** * Test locks for rename or copy operation cross-storage * - * @dataProvider lockFileRenameOrCopyCrossStorageDataProvider * * @param string $viewOperation operation to be done on the view * @param string $storageOperation operation to be mocked on the storage * @param int $expectedLockTypeSourceDuring expected lock type on source file during - * the operation + * the operation */ - public function testLockFileRenameCrossStorage($viewOperation, $storageOperation, $expectedLockTypeSourceDuring) { + #[\PHPUnit\Framework\Attributes\DataProvider('lockFileRenameOrCopyCrossStorageDataProvider')] + public function testLockFileRenameCrossStorage($viewOperation, $storageOperation, $expectedLockTypeSourceDuring): void { $view = new View('/' . $this->user . '/files/'); /** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage */ $storage = $this->getMockBuilder(Temporary::class) - ->setMethods([$storageOperation]) + ->onlyMethods([$storageOperation]) ->getMock(); /** @var Temporary|\PHPUnit\Framework\MockObject\MockObject $storage2 */ $storage2 = $this->getMockBuilder(Temporary::class) - ->setMethods([$storageOperation, 'getMetaData', 'filemtime']) + ->onlyMethods([$storageOperation, 'getMetaData', 'filemtime']) ->getMock(); $storage2->expects($this->any()) ->method('getMetaData') - ->will($this->returnValue([ + ->willReturn([ 'mtime' => 1885434487, 'etag' => '', 'mimetype' => 'text/plain', 'permissions' => Constants::PERMISSION_ALL, 'size' => 3 - ])); + ]); $storage2->expects($this->any()) ->method('filemtime') ->willReturn(123456789); @@ -2326,10 +2443,14 @@ class ViewTest extends \Test\TestCase { $sourcePath = 'original.txt'; $targetPath = 'substorage/target.txt'; + /* Disable encryption wrapper to avoid it intercepting mocked call */ + Server::get(IStorageFactory::class)->removeStorageWrapper('oc_encryption'); + Filesystem::mount($storage, [], $this->user . '/'); Filesystem::mount($storage2, [], $this->user . '/files/substorage'); $storage->mkdir('files'); $view->file_put_contents($sourcePath, 'meh'); + $storage2->getUpdater()->update(''); $storage->expects($this->never()) ->method($storageOperation); @@ -2367,7 +2488,7 @@ class ViewTest extends \Test\TestCase { /** * Test locks when moving a mount point */ - public function testLockMoveMountPoint() { + public function testLockMoveMountPoint(): void { self::loginAsUser('test'); [$mount] = $this->createTestMovableMountPoints([ @@ -2434,28 +2555,28 @@ class ViewTest extends \Test\TestCase { * @param int $lockTypePre variable to receive lock type that was active in the pre-hook * @param int $lockTypePost variable to receive lock type that was active in the post-hook * @param bool $onMountPoint true to check the mount point instead of the - * mounted storage + * mounted storage */ private function connectMockHooks($hookType, $view, $path, &$lockTypePre, &$lockTypePost, $onMountPoint = false) { if ($hookType === null) { return; } - $eventHandler = $this->getMockBuilder(\stdclass::class) - ->setMethods(['preCallback', 'postCallback']) + $eventHandler = $this->getMockBuilder(TestEventHandler::class) + ->onlyMethods(['preCallback', 'postCallback']) ->getMock(); $eventHandler->expects($this->any()) ->method('preCallback') ->willReturnCallback( - function () use ($view, $path, $onMountPoint, &$lockTypePre) { + function () use ($view, $path, $onMountPoint, &$lockTypePre): void { $lockTypePre = $this->getFileLockType($view, $path, $onMountPoint); } ); $eventHandler->expects($this->any()) ->method('postCallback') ->willReturnCallback( - function () use ($view, $path, $onMountPoint, &$lockTypePost) { + function () use ($view, $path, $onMountPoint, &$lockTypePost): void { $lockTypePost = $this->getFileLockType($view, $path, $onMountPoint); } ); @@ -2482,7 +2603,7 @@ class ViewTest extends \Test\TestCase { * @param View $view view * @param string $path path * @param bool $onMountPoint true to check the mount point instead of the - * mounted storage + * mounted storage * * @return int lock type or null if file was not locked */ @@ -2496,7 +2617,7 @@ class ViewTest extends \Test\TestCase { } - public function testRemoveMoveableMountPoint() { + public function testRemoveMoveableMountPoint(): void { $mountPoint = '/' . $this->user . '/files/mount/'; // Mock the mount point @@ -2516,8 +2637,8 @@ class ViewTest extends \Test\TestCase { Filesystem::getMountManager()->addMount($mount); // Listen for events - $eventHandler = $this->getMockBuilder(\stdclass::class) - ->setMethods(['umount', 'post_umount']) + $eventHandler = $this->getMockBuilder(TestEventHandler::class) + ->onlyMethods(['umount', 'post_umount']) ->getMock(); $eventHandler->expects($this->once()) ->method('umount') @@ -2543,7 +2664,7 @@ class ViewTest extends \Test\TestCase { $this->assertEquals('foo', $view->rmdir('mount')); } - public function mimeFilterProvider() { + public static function mimeFilterProvider(): array { return [ [null, ['test1.txt', 'test2.txt', 'test3.md', 'test4.png']], ['text/plain', ['test1.txt', 'test2.txt']], @@ -2555,9 +2676,9 @@ class ViewTest extends \Test\TestCase { /** * @param string $filter * @param string[] $expected - * @dataProvider mimeFilterProvider */ - public function testGetDirectoryContentMimeFilter($filter, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('mimeFilterProvider')] + public function testGetDirectoryContentMimeFilter($filter, $expected): void { $storage1 = new Temporary(); $root = self::getUniqueID('/'); Filesystem::mount($storage1, [], $root . '/'); @@ -2578,7 +2699,7 @@ class ViewTest extends \Test\TestCase { $this->assertEquals($expected, $files); } - public function testFilePutContentsClearsChecksum() { + public function testFilePutContentsClearsChecksum(): void { $storage = new Temporary([]); $scanner = $storage->getScanner(); $storage->file_put_contents('foo.txt', 'bar'); @@ -2599,7 +2720,7 @@ class ViewTest extends \Test\TestCase { $this->assertEquals('', $data->getChecksum()); } - public function testDeleteGhostFile() { + public function testDeleteGhostFile(): void { $storage = new Temporary([]); $scanner = $storage->getScanner(); $cache = $storage->getCache(); @@ -2622,7 +2743,7 @@ class ViewTest extends \Test\TestCase { $this->assertEquals(0, $newInfo->getSize()); } - public function testDeleteGhostFolder() { + public function testDeleteGhostFolder(): void { $storage = new Temporary([]); $scanner = $storage->getScanner(); $cache = $storage->getCache(); @@ -2648,10 +2769,10 @@ class ViewTest extends \Test\TestCase { $this->assertEquals(0, $newInfo->getSize()); } - public function testCreateParentDirectories() { + public function testCreateParentDirectories(): void { $view = $this->getMockBuilder(View::class) ->disableOriginalConstructor() - ->setMethods([ + ->onlyMethods([ 'is_file', 'file_exists', 'mkdir', @@ -2660,37 +2781,34 @@ class ViewTest extends \Test\TestCase { $view->expects($this->exactly(3)) ->method('is_file') - ->withConsecutive( - ['/new'], - ['/new/folder'], - ['/new/folder/structure'], - ) - ->willReturn(false); + ->willReturnMap([ + ['/new', false], + ['/new/folder', false], + ['/new/folder/structure', false], + ]); $view->expects($this->exactly(3)) ->method('file_exists') - ->withConsecutive( - ['/new'], - ['/new/folder'], - ['/new/folder/structure'], - )->willReturnOnConsecutiveCalls( - true, - false, - false, - ); + ->willReturnMap([ + ['/new', true], + ['/new/folder', false], + ['/new/folder/structure', false], + ]); + + $calls = ['/new/folder', '/new/folder/structure']; $view->expects($this->exactly(2)) ->method('mkdir') - ->withConsecutive( - ['/new/folder'], - ['/new/folder/structure'], - ); + ->willReturnCallback(function ($dir) use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, $dir); + }); $this->assertTrue(self::invokePrivate($view, 'createParentDirectories', ['/new/folder/structure'])); } - public function testCreateParentDirectoriesWithExistingFile() { + public function testCreateParentDirectoriesWithExistingFile(): void { $view = $this->getMockBuilder(View::class) ->disableOriginalConstructor() - ->setMethods([ + ->onlyMethods([ 'is_file', 'file_exists', 'mkdir', @@ -2705,7 +2823,7 @@ class ViewTest extends \Test\TestCase { $this->assertFalse(self::invokePrivate($view, 'createParentDirectories', ['/file.txt/folder/structure'])); } - public function testCacheExtension() { + public function testCacheExtension(): void { $storage = new Temporary([]); $scanner = $storage->getScanner(); $storage->file_put_contents('foo.txt', 'bar'); @@ -2725,7 +2843,7 @@ class ViewTest extends \Test\TestCase { $this->assertEquals(0, $info->getCreationTime()); } - public function testFopenGone() { + public function testFopenGone(): void { $storage = new Temporary([]); $scanner = $storage->getScanner(); $storage->file_put_contents('foo.txt', 'bar'); @@ -2743,4 +2861,43 @@ class ViewTest extends \Test\TestCase { $this->assertFalse($cache->inCache('foo.txt')); } + + public function testMountpointParentsCreated(): void { + $storage1 = $this->getTestStorage(); + Filesystem::mount($storage1, [], '/'); + + $storage2 = $this->getTestStorage(); + Filesystem::mount($storage2, [], '/A/B/C'); + + $rootView = new View(''); + + $folderData = $rootView->getDirectoryContent('/'); + $this->assertCount(4, $folderData); + $this->assertEquals('folder', $folderData[0]['name']); + $this->assertEquals('foo.png', $folderData[1]['name']); + $this->assertEquals('foo.txt', $folderData[2]['name']); + $this->assertEquals('A', $folderData[3]['name']); + + $folderData = $rootView->getDirectoryContent('/A'); + $this->assertCount(1, $folderData); + $this->assertEquals('B', $folderData[0]['name']); + + $folderData = $rootView->getDirectoryContent('/A/B'); + $this->assertCount(1, $folderData); + $this->assertEquals('C', $folderData[0]['name']); + + $folderData = $rootView->getDirectoryContent('/A/B/C'); + $this->assertCount(3, $folderData); + $this->assertEquals('folder', $folderData[0]['name']); + $this->assertEquals('foo.png', $folderData[1]['name']); + $this->assertEquals('foo.txt', $folderData[2]['name']); + } + + public function testCopyPreservesContent() { + $viewUser1 = new View('/' . 'userId' . '/files'); + $viewUser1->mkdir(''); + $viewUser1->file_put_contents('foo.txt', 'foo'); + $viewUser1->copy('foo.txt', 'bar.txt'); + $this->assertEquals('foo', $viewUser1->file_get_contents('bar.txt')); + } } |