aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_external/tests/Storage/SmbTest.php
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_external/tests/Storage/SmbTest.php')
-rw-r--r--apps/files_external/tests/Storage/SmbTest.php176
1 files changed, 176 insertions, 0 deletions
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(''));
+ }
+}