aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_external/tests/Storage
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_external/tests/Storage')
-rw-r--r--apps/files_external/tests/Storage/Amazons3MultiPartTest.php49
-rw-r--r--apps/files_external/tests/Storage/Amazons3Test.php47
-rw-r--r--apps/files_external/tests/Storage/FtpTest.php90
-rw-r--r--apps/files_external/tests/Storage/OwncloudTest.php43
-rw-r--r--apps/files_external/tests/Storage/SFTP_KeyTest.php81
-rw-r--r--apps/files_external/tests/Storage/SftpTest.php136
-rw-r--r--apps/files_external/tests/Storage/SmbTest.php176
-rw-r--r--apps/files_external/tests/Storage/SwiftTest.php61
-rw-r--r--apps/files_external/tests/Storage/VersionedAmazonS3Test.php37
-rw-r--r--apps/files_external/tests/Storage/WebdavTest.php57
10 files changed, 777 insertions, 0 deletions
diff --git a/apps/files_external/tests/Storage/Amazons3MultiPartTest.php b/apps/files_external/tests/Storage/Amazons3MultiPartTest.php
new file mode 100644
index 00000000000..aa3925899f3
--- /dev/null
+++ b/apps/files_external/tests/Storage/Amazons3MultiPartTest.php
@@ -0,0 +1,49 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Files_External\Tests\Storage;
+
+use OCA\Files_External\Lib\Storage\AmazonS3;
+
+/**
+ * Class Amazons3Test
+ *
+ * @group DB
+ * @group S3
+ *
+ * @package OCA\Files_External\Tests\Storage
+ */
+class Amazons3MultiPartTest extends \Test\Files\Storage\Storage {
+ private $config;
+ /** @var AmazonS3 */
+ protected $instance;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->config = include('files_external/tests/config.amazons3.php');
+ if (!is_array($this->config) || !$this->config['run']) {
+ $this->markTestSkipped('AmazonS3 backend not configured');
+ }
+ $this->instance = new AmazonS3($this->config + [
+ 'putSizeLimit' => 1,
+ 'copySizeLimit' => 1,
+ ]);
+ }
+
+ protected function tearDown(): void {
+ if ($this->instance) {
+ $this->instance->rmdir('');
+ }
+
+ parent::tearDown();
+ }
+
+ public function testStat(): void {
+ $this->markTestSkipped('S3 doesn\'t update the parents folder mtime');
+ }
+}
diff --git a/apps/files_external/tests/Storage/Amazons3Test.php b/apps/files_external/tests/Storage/Amazons3Test.php
new file mode 100644
index 00000000000..d02dec0230c
--- /dev/null
+++ b/apps/files_external/tests/Storage/Amazons3Test.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCA\Files_External\Tests\Storage;
+
+use OCA\Files_External\Lib\Storage\AmazonS3;
+
+/**
+ * Class Amazons3Test
+ *
+ * @group DB
+ * @group S3
+ *
+ * @package OCA\Files_External\Tests\Storage
+ */
+class Amazons3Test extends \Test\Files\Storage\Storage {
+ protected $config;
+ /** @var AmazonS3 */
+ protected $instance;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->config = include('files_external/tests/config.amazons3.php');
+ if (!is_array($this->config) || !$this->config['run']) {
+ $this->markTestSkipped('AmazonS3 backend not configured');
+ }
+ $this->instance = new AmazonS3($this->config);
+ }
+
+ protected function tearDown(): void {
+ if ($this->instance) {
+ $this->instance->rmdir('');
+ }
+
+ parent::tearDown();
+ }
+
+ public function testStat(): void {
+ $this->markTestSkipped('S3 doesn\'t update the parents folder mtime');
+ }
+}
diff --git a/apps/files_external/tests/Storage/FtpTest.php b/apps/files_external/tests/Storage/FtpTest.php
new file mode 100644
index 00000000000..095a5236049
--- /dev/null
+++ b/apps/files_external/tests/Storage/FtpTest.php
@@ -0,0 +1,90 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCA\Files_External\Tests\Storage;
+
+use OCA\Files_External\Lib\Storage\FTP;
+
+/**
+ * Class FtpTest
+ *
+ * @group DB
+ *
+ * @package OCA\Files_External\Tests\Storage
+ */
+class FtpTest extends \Test\Files\Storage\Storage {
+ private $config;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $id = $this->getUniqueID();
+ $this->config = include('files_external/tests/config.ftp.php');
+ if (! is_array($this->config) or ! $this->config['run']) {
+ $this->markTestSkipped('FTP backend not configured');
+ }
+ $rootInstance = new FTP($this->config);
+ $rootInstance->mkdir($id);
+
+ $this->config['root'] .= '/' . $id; //make sure we have an new empty folder to work in
+ $this->instance = new FTP($this->config);
+ }
+
+ protected function tearDown(): void {
+ if ($this->instance) {
+ $this->instance->rmdir('');
+ }
+ $this->instance = null;
+
+ parent::tearDown();
+ }
+
+ /**
+ * ftp has no proper way to handle spaces at the end of file names
+ */
+ public static function directoryProvider(): array {
+ return array_filter(parent::directoryProvider(), function ($item) {
+ return substr($item[0], -1) !== ' ';
+ });
+ }
+
+
+ /**
+ * mtime for folders is only with a minute resolution
+ */
+ public function testStat(): void {
+ $textFile = \OC::$SERVERROOT . '/tests/data/lorem.txt';
+ $ctimeStart = time();
+ $this->instance->file_put_contents('/lorem.txt', file_get_contents($textFile));
+ $this->assertTrue($this->instance->isReadable('/lorem.txt'));
+ $ctimeEnd = time();
+ $mTime = $this->instance->filemtime('/lorem.txt');
+ $this->assertTrue($this->instance->hasUpdated('/lorem.txt', $ctimeStart - 5));
+ $this->assertTrue($this->instance->hasUpdated('/', $ctimeStart - 61));
+
+ // check that ($ctimeStart - 5) <= $mTime <= ($ctimeEnd + 1)
+ $this->assertGreaterThanOrEqual(($ctimeStart - 5), $mTime);
+ $this->assertLessThanOrEqual(($ctimeEnd + 1), $mTime);
+ $this->assertEquals(filesize($textFile), $this->instance->filesize('/lorem.txt'));
+
+ $stat = $this->instance->stat('/lorem.txt');
+ //only size and mtime are required in the result
+ $this->assertEquals($stat['size'], $this->instance->filesize('/lorem.txt'));
+ $this->assertEquals($stat['mtime'], $mTime);
+
+ if ($this->instance->touch('/lorem.txt', 100) !== false) {
+ $mTime = $this->instance->filemtime('/lorem.txt');
+ $this->assertEquals($mTime, 100);
+ }
+
+ $mtimeStart = time();
+
+ $this->instance->unlink('/lorem.txt');
+ $this->assertTrue($this->instance->hasUpdated('/', $mtimeStart - 61));
+ }
+}
diff --git a/apps/files_external/tests/Storage/OwncloudTest.php b/apps/files_external/tests/Storage/OwncloudTest.php
new file mode 100644
index 00000000000..ab6cd443dba
--- /dev/null
+++ b/apps/files_external/tests/Storage/OwncloudTest.php
@@ -0,0 +1,43 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCA\Files_External\Tests\Storage;
+
+use OCA\Files_External\Lib\Storage\OwnCloud;
+
+/**
+ * Class OwnCloudTest
+ *
+ * @group DB
+ *
+ * @package OCA\Files_External\Tests\Storage
+ */
+class OwncloudTest extends \Test\Files\Storage\Storage {
+ private $config;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $id = $this->getUniqueID();
+ $this->config = include('files_external/tests/config.php');
+ if (! is_array($this->config) or ! isset($this->config['owncloud']) or ! $this->config['owncloud']['run']) {
+ $this->markTestSkipped('Nextcloud backend not configured');
+ }
+ $this->config['owncloud']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
+ $this->instance = new OwnCloud($this->config['owncloud']);
+ $this->instance->mkdir('/');
+ }
+
+ protected function tearDown(): void {
+ if ($this->instance) {
+ $this->instance->rmdir('/');
+ }
+
+ parent::tearDown();
+ }
+}
diff --git a/apps/files_external/tests/Storage/SFTP_KeyTest.php b/apps/files_external/tests/Storage/SFTP_KeyTest.php
new file mode 100644
index 00000000000..17e2087f91b
--- /dev/null
+++ b/apps/files_external/tests/Storage/SFTP_KeyTest.php
@@ -0,0 +1,81 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCA\Files_External\Tests\Storage;
+
+use OCA\Files_External\Lib\Storage\SFTP_Key;
+
+/**
+ * Class SFTP_KeyTest
+ *
+ * @group DB
+ *
+ * @package OCA\Files_External\Tests\Storage
+ */
+class SFTP_KeyTest extends \Test\Files\Storage\Storage {
+ private $config;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $id = $this->getUniqueID();
+ $this->config = include('files_external/tests/config.php');
+ if (! is_array($this->config) or ! isset($this->config['sftp_key']) or ! $this->config['sftp_key']['run']) {
+ $this->markTestSkipped('SFTP with key backend not configured');
+ }
+ // Make sure we have an new empty folder to work in
+ $this->config['sftp_key']['root'] .= '/' . $id;
+ $this->instance = new SFTP_Key($this->config['sftp_key']);
+ $this->instance->mkdir('/');
+ }
+
+ protected function tearDown(): void {
+ if ($this->instance) {
+ $this->instance->rmdir('/');
+ }
+
+ parent::tearDown();
+ }
+
+
+ public function testInvalidAddressShouldThrowException(): void {
+ $this->expectException(\InvalidArgumentException::class);
+
+ // I'd use example.com for this, but someone decided to break the spec and make it resolve
+ $this->instance->assertHostAddressValid('notarealaddress...');
+ }
+
+ public function testValidAddressShouldPass(): void {
+ $this->assertTrue($this->instance->assertHostAddressValid('localhost'));
+ }
+
+
+ public function testNegativePortNumberShouldThrowException(): void {
+ $this->expectException(\InvalidArgumentException::class);
+
+ $this->instance->assertPortNumberValid('-1');
+ }
+
+
+ public function testNonNumericalPortNumberShouldThrowException(): void {
+ $this->expectException(\InvalidArgumentException::class);
+
+ $this->instance->assertPortNumberValid('a');
+ }
+
+
+ public function testHighPortNumberShouldThrowException(): void {
+ $this->expectException(\InvalidArgumentException::class);
+
+ $this->instance->assertPortNumberValid('65536');
+ }
+
+ public function testValidPortNumberShouldPass(): void {
+ $this->assertTrue($this->instance->assertPortNumberValid('22222'));
+ }
+}
diff --git a/apps/files_external/tests/Storage/SftpTest.php b/apps/files_external/tests/Storage/SftpTest.php
new file mode 100644
index 00000000000..ebfc8ab3c1f
--- /dev/null
+++ b/apps/files_external/tests/Storage/SftpTest.php
@@ -0,0 +1,136 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCA\Files_External\Tests\Storage;
+
+use OCA\Files_External\Lib\Storage\SFTP;
+
+/**
+ * Class SftpTest
+ *
+ * @group DB
+ *
+ * @package OCA\Files_External\Tests\Storage
+ */
+class SftpTest extends \Test\Files\Storage\Storage {
+ /**
+ * @var SFTP instance
+ */
+ protected $instance;
+
+ private $config;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $id = $this->getUniqueID();
+ $this->config = include('files_external/tests/config.sftp.php');
+ if (!is_array($this->config) or !$this->config['run']) {
+ $this->markTestSkipped('SFTP backend not configured');
+ }
+ $this->config['root'] .= '/' . $id; //make sure we have an new empty folder to work in
+ $this->instance = new SFTP($this->config);
+ $this->instance->mkdir('/');
+ }
+
+ protected function tearDown(): void {
+ if ($this->instance) {
+ $this->instance->rmdir('/');
+ }
+
+ parent::tearDown();
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('configProvider')]
+ public function testStorageId($config, $expectedStorageId): void {
+ $instance = new SFTP($config);
+ $this->assertEquals($expectedStorageId, $instance->getId());
+ }
+
+ public static function configProvider(): array {
+ return [
+ [
+ // no root path
+ [
+ 'run' => true,
+ 'host' => 'somehost',
+ 'user' => 'someuser',
+ 'password' => 'somepassword',
+ 'root' => '',
+ ],
+ 'sftp::someuser@somehost//',
+ ],
+ [
+ // without leading nor trailing slash
+ [
+ 'run' => true,
+ 'host' => 'somehost',
+ 'user' => 'someuser',
+ 'password' => 'somepassword',
+ 'root' => 'remotedir/subdir',
+ ],
+ 'sftp::someuser@somehost//remotedir/subdir/',
+ ],
+ [
+ // regular path
+ [
+ 'run' => true,
+ 'host' => 'somehost',
+ 'user' => 'someuser',
+ 'password' => 'somepassword',
+ 'root' => '/remotedir/subdir/',
+ ],
+ 'sftp::someuser@somehost//remotedir/subdir/',
+ ],
+ [
+ // different port
+ [
+ 'run' => true,
+ 'host' => 'somehost:8822',
+ 'user' => 'someuser',
+ 'password' => 'somepassword',
+ 'root' => 'remotedir/subdir/',
+ ],
+ 'sftp::someuser@somehost:8822//remotedir/subdir/',
+ ],
+ [
+ // ipv6 with port
+ [
+ 'run' => true,
+ 'host' => 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329',
+ 'user' => 'someuser',
+ 'password' => 'somepassword',
+ 'root' => 'remotedir/subdir/',
+ ],
+ 'sftp::someuser@FE80:0000:0000:0000:0202:B3FF:FE1E:8329//remotedir/subdir/',
+ ],
+ [
+ // ipv6 without port
+ [
+ 'run' => true,
+ 'host' => 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329:8822',
+ 'user' => 'someuser',
+ 'password' => 'somepassword',
+ 'root' => 'remotedir/subdir/',
+ ],
+ 'sftp::someuser@FE80:0000:0000:0000:0202:B3FF:FE1E:8329:8822//remotedir/subdir/',
+ ],
+ [
+ // collapsed ipv6 with port
+ [
+ 'run' => true,
+ 'host' => 'FE80::0202:B3FF:FE1E:8329:8822',
+ 'user' => 'someuser',
+ 'password' => 'somepassword',
+ 'root' => 'remotedir/subdir/',
+ ],
+ 'sftp::someuser@FE80::0202:B3FF:FE1E:8329:8822//remotedir/subdir/',
+ ],
+ ];
+ }
+}
diff --git a/apps/files_external/tests/Storage/SmbTest.php b/apps/files_external/tests/Storage/SmbTest.php
new file mode 100644
index 00000000000..afcb5c1034f
--- /dev/null
+++ b/apps/files_external/tests/Storage/SmbTest.php
@@ -0,0 +1,176 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCA\Files_External\Tests\Storage;
+
+use OC\Files\Notify\Change;
+use OC\Files\Notify\RenameChange;
+use OCA\Files_External\Lib\Storage\SMB;
+use OCP\Files\Notify\IChange;
+use PHPUnit\Framework\ExpectationFailedException;
+
+/**
+ * Class SmbTest
+ *
+ * @group DB
+ *
+ * @package OCA\Files_External\Tests\Storage
+ */
+class SmbTest extends \Test\Files\Storage\Storage {
+ /**
+ * @var SMB instance
+ */
+ protected $instance;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $id = $this->getUniqueID();
+ $config = include('files_external/tests/config.smb.php');
+ if (!is_array($config) or !$config['run']) {
+ $this->markTestSkipped('Samba backend not configured');
+ }
+ if (substr($config['root'], -1, 1) != '/') {
+ $config['root'] .= '/';
+ }
+ $config['root'] .= $id; //make sure we have an new empty folder to work in
+ $this->instance = new SMB($config);
+ $this->instance->mkdir('/');
+ }
+
+ protected function tearDown(): void {
+ if ($this->instance) {
+ $this->instance->rmdir('');
+ }
+
+ parent::tearDown();
+ }
+
+ public static function directoryProvider(): array {
+ // doesn't support leading/trailing spaces
+ return [['folder']];
+ }
+
+ public function testRenameWithSpaces(): void {
+ $this->instance->mkdir('with spaces');
+ $result = $this->instance->rename('with spaces', 'foo bar');
+ $this->assertTrue($result);
+ $this->assertTrue($this->instance->is_dir('foo bar'));
+ }
+
+ public function testStorageId(): void {
+ $this->instance = new SMB([
+ 'host' => 'testhost',
+ 'user' => 'testuser',
+ 'password' => 'somepass',
+ 'share' => 'someshare',
+ 'root' => 'someroot',
+ ]);
+ $this->assertEquals('smb::testuser@testhost//someshare//someroot/', $this->instance->getId());
+ $this->instance = null;
+ }
+
+ public function testNotifyGetChanges(): void {
+ $lastError = null;
+ for ($i = 0; $i < 5; $i++) {
+ try {
+ $this->tryTestNotifyGetChanges();
+ return;
+ } catch (ExpectationFailedException $e) {
+ $lastError = $e;
+ $this->tearDown();
+ $this->setUp();
+ sleep(1);
+ }
+ }
+ throw $lastError;
+ }
+
+ private function tryTestNotifyGetChanges(): void {
+ $notifyHandler = $this->instance->notify('');
+ sleep(1); //give time for the notify to start
+ $this->instance->file_put_contents('/newfile.txt', 'test content');
+ sleep(1);
+ $this->instance->rename('/newfile.txt', 'renamed.txt');
+ sleep(1);
+ $this->instance->unlink('/renamed.txt');
+ sleep(1); //time for all changes to be processed
+
+ /** @var IChange[] $changes */
+ $changes = [];
+ $count = 0;
+ // wait up to 10 seconds for incoming changes
+ while (count($changes) < 3 && $count < 10) {
+ $changes = array_merge($changes, $notifyHandler->getChanges());
+ $count++;
+ sleep(1);
+ }
+ $notifyHandler->stop();
+
+ // depending on the server environment, the initial create might be detected as a change instead
+ if ($changes[0]->getType() === IChange::MODIFIED) {
+ $expected = [
+ new Change(IChange::MODIFIED, 'newfile.txt'),
+ new RenameChange(IChange::RENAMED, 'newfile.txt', 'renamed.txt'),
+ new Change(IChange::REMOVED, 'renamed.txt')
+ ];
+ } else {
+ $expected = [
+ new Change(IChange::ADDED, 'newfile.txt'),
+ new RenameChange(IChange::RENAMED, 'newfile.txt', 'renamed.txt'),
+ new Change(IChange::REMOVED, 'renamed.txt')
+ ];
+ }
+
+ foreach ($expected as $expectedChange) {
+ $this->assertTrue(in_array($expectedChange, $changes), "Expected changes are:\n" . print_r($expected, true) . PHP_EOL . 'Expected to find: ' . PHP_EOL . print_r($expectedChange, true) . "\nGot:\n" . print_r($changes, true));
+ }
+ }
+
+ public function testNotifyListen(): void {
+ $notifyHandler = $this->instance->notify('');
+ usleep(100 * 1000); //give time for the notify to start
+ $this->instance->file_put_contents('/newfile.txt', 'test content');
+ $this->instance->unlink('/newfile.txt');
+ usleep(100 * 1000); //time for all changes to be processed
+
+ $result = null;
+
+ // since the notify handler buffers until we start listening we will get the above changes
+ $notifyHandler->listen(function (IChange $change) use (&$result) {
+ $result = $change;
+ return false;//stop listening
+ });
+
+ // depending on the server environment, the initial create might be detected as a change instead
+ if ($result->getType() === IChange::ADDED) {
+ $this->assertEquals(new Change(IChange::ADDED, 'newfile.txt'), $result);
+ } else {
+ $this->assertEquals(new Change(IChange::MODIFIED, 'newfile.txt'), $result);
+ }
+ }
+
+ public function testRenameRoot(): void {
+ // root can't be renamed
+ $this->assertFalse($this->instance->rename('', 'foo1'));
+
+ $this->instance->mkdir('foo2');
+ $this->assertFalse($this->instance->rename('foo2', ''));
+ $this->instance->rmdir('foo2');
+ }
+
+ public function testUnlinkRoot(): void {
+ // root can't be deleted
+ $this->assertFalse($this->instance->unlink(''));
+ }
+
+ public function testRmdirRoot(): void {
+ // root can't be deleted
+ $this->assertFalse($this->instance->rmdir(''));
+ }
+}
diff --git a/apps/files_external/tests/Storage/SwiftTest.php b/apps/files_external/tests/Storage/SwiftTest.php
new file mode 100644
index 00000000000..17037e76ee3
--- /dev/null
+++ b/apps/files_external/tests/Storage/SwiftTest.php
@@ -0,0 +1,61 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCA\Files_External\Tests\Storage;
+
+use GuzzleHttp\Exception\ClientException;
+use OCA\Files_External\Lib\Storage\Swift;
+
+/**
+ * Class SwiftTest
+ *
+ * @group DB
+ *
+ * @package OCA\Files_External\Tests\Storage
+ */
+class SwiftTest extends \Test\Files\Storage\Storage {
+ private $config;
+
+ /**
+ * @var Swift instance
+ */
+ protected $instance;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->config = include('files_external/tests/config.swift.php');
+ if (!is_array($this->config) or !$this->config['run']) {
+ $this->markTestSkipped('OpenStack Object Storage backend not configured');
+ }
+ $this->instance = new Swift($this->config);
+ }
+
+ protected function tearDown(): void {
+ if ($this->instance) {
+ try {
+ $container = $this->instance->getContainer();
+
+ $objects = $container->listObjects();
+ foreach ($objects as $object) {
+ $object->delete();
+ }
+
+ $container->delete();
+ } catch (ClientException $e) {
+ // container didn't exist, so we don't need to delete it
+ }
+ }
+
+ parent::tearDown();
+ }
+
+ public function testStat(): void {
+ $this->markTestSkipped('Swift doesn\'t update the parents folder mtime');
+ }
+}
diff --git a/apps/files_external/tests/Storage/VersionedAmazonS3Test.php b/apps/files_external/tests/Storage/VersionedAmazonS3Test.php
new file mode 100644
index 00000000000..9d413620292
--- /dev/null
+++ b/apps/files_external/tests/Storage/VersionedAmazonS3Test.php
@@ -0,0 +1,37 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Files_External\Tests\Storage;
+
+/**
+ * @group DB
+ * @group S3
+ */
+class VersionedAmazonS3Test extends Amazons3Test {
+ protected function setUp(): void {
+ parent::setUp();
+ try {
+ $this->instance->getConnection()->putBucketVersioning([
+ 'Bucket' => $this->instance->getBucket(),
+ 'VersioningConfiguration' => [
+ 'Status' => 'Enabled',
+ ],
+ ]);
+ } catch (\Exception $e) {
+ $this->markTestSkipped("s3 backend doesn't seem to support versioning");
+ }
+ }
+
+ public function testCopyOverWriteDirectory(): void {
+ if (isset($this->config['minio'])) {
+ $this->markTestSkipped('MinIO has a bug with batch deletion on versioned storages, see https://github.com/minio/minio/issues/21366');
+ }
+
+ parent::testCopyOverWriteDirectory();
+ }
+}
diff --git a/apps/files_external/tests/Storage/WebdavTest.php b/apps/files_external/tests/Storage/WebdavTest.php
new file mode 100644
index 00000000000..a8de178effd
--- /dev/null
+++ b/apps/files_external/tests/Storage/WebdavTest.php
@@ -0,0 +1,57 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCA\Files_External\Tests\Storage;
+
+use OC\Files\Storage\DAV;
+use OC\Files\Type\Detection;
+use OCP\Files\IMimeTypeDetector;
+use OCP\Server;
+
+/**
+ * Class WebdavTest
+ *
+ * @group DB
+ *
+ * @package OCA\Files_External\Tests\Storage
+ */
+class WebdavTest extends \Test\Files\Storage\Storage {
+ protected function setUp(): void {
+ parent::setUp();
+
+ $id = $this->getUniqueID();
+ $config = include('files_external/tests/config.webdav.php');
+ if (!is_array($config) or !$config['run']) {
+ $this->markTestSkipped('WebDAV backend not configured');
+ }
+ if (isset($config['wait'])) {
+ $this->waitDelay = $config['wait'];
+ }
+ $config['root'] .= '/' . $id; //make sure we have an new empty folder to work in
+ $this->instance = new DAV($config);
+ $this->instance->mkdir('/');
+ }
+
+ protected function tearDown(): void {
+ if ($this->instance) {
+ $this->instance->rmdir('/');
+ }
+
+ parent::tearDown();
+ }
+
+ public function testMimetypeFallback(): void {
+ $this->instance->file_put_contents('foo.bar', 'asd');
+
+ /** @var Detection $mimeDetector */
+ $mimeDetector = Server::get(IMimeTypeDetector::class);
+ $mimeDetector->registerType('bar', 'application/x-bar');
+
+ $this->assertEquals('application/x-bar', $this->instance->getMimeType('foo.bar'));
+ }
+}