From 0a819118995774001197435de9121c96814943ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Tue, 30 Jul 2024 03:04:40 +0200 Subject: [PATCH] test: Add integration tests for saving external userglobal storages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the external storage uses the Nextcloud server itself the number of workers of the PHP process running the Nextcloud server had to be increased. Otherwise if a request is sent for the external storage while handling a request from the integration tests a deadlock would occur. Signed-off-by: Daniel Calviño Sánchez --- .../features/bootstrap/BasicStructure.php | 2 +- .../features/bootstrap/ExternalStorage.php | 103 ++++++++++++++++++ .../features/bootstrap/FeatureContext.php | 1 + .../files_features/external-storage.feature | 30 +++++ build/integration/run.sh | 2 +- 5 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 build/integration/features/bootstrap/ExternalStorage.php diff --git a/build/integration/features/bootstrap/BasicStructure.php b/build/integration/features/bootstrap/BasicStructure.php index 6a1cc7e1ada7f..57f4b7de2e4f1 100644 --- a/build/integration/features/bootstrap/BasicStructure.php +++ b/build/integration/features/bootstrap/BasicStructure.php @@ -327,7 +327,7 @@ public function sendingAToWithRequesttoken($method, $url, $body = null) { $fd = $body->getRowsHash(); $options['form_params'] = $fd; } elseif ($body) { - $options = array_merge($options, $body); + $options = array_merge_recursive($options, $body); } $client = new Client(); diff --git a/build/integration/features/bootstrap/ExternalStorage.php b/build/integration/features/bootstrap/ExternalStorage.php new file mode 100644 index 0000000000000..2a73f22c1b44c --- /dev/null +++ b/build/integration/features/bootstrap/ExternalStorage.php @@ -0,0 +1,103 @@ +storageIds as $storageId) { + $this->deleteStorage($storageId); + } + $this->storageIds = []; + } + + private function deleteStorage(string $storageId): void { + // Based on "runOcc" from CommandLine trait + $args = ['files_external:delete', '--yes', $storageId]; + $args = array_map(function ($arg) { + return escapeshellarg($arg); + }, $args); + $args[] = '--no-ansi --no-warnings'; + $args = implode(' ', $args); + + $descriptor = [ + 0 => ['pipe', 'r'], + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; + $process = proc_open('php console.php ' . $args, $descriptor, $pipes, $ocPath = '../..'); + $lastStdOut = stream_get_contents($pipes[1]); + proc_close($process); + } + + /** + * @When logged in user creates external global storage + * + * @param TableNode $fields + */ + public function loggedInUserCreatesExternalGlobalStorage(TableNode $fields): void { + $this->sendJsonWithRequestToken('POST', '/index.php/apps/files_external/globalstorages', $fields); + $this->theHTTPStatusCodeShouldBe('201'); + + $this->lastExternalStorageData = json_decode($this->response->getBody(), $asAssociativeArray = true); + + $this->storageIds[] = $this->lastExternalStorageData['id']; + } + + /** + * @When logged in user updates last external userglobal storage + * + * @param TableNode $fields + */ + public function loggedInUserUpdatesLastExternalUserglobalStorage(TableNode $fields): void { + $this->sendJsonWithRequestToken('PUT', '/index.php/apps/files_external/userglobalstorages/' . $this->lastExternalStorageData['id'], $fields); + $this->theHTTPStatusCodeShouldBe('200'); + + $this->lastExternalStorageData = json_decode($this->response->getBody(), $asAssociativeArray = true); + } + + /** + * @Then fields of last external storage match with + * + * @param TableNode $fields + */ + public function fieldsOfLastExternalStorageMatchWith(TableNode $fields): void { + foreach ($fields->getRowsHash() as $expectedField => $expectedValue) { + if (!array_key_exists($expectedField, $this->lastExternalStorageData)) { + Assert::fail("$expectedField was not found in response"); + } + + Assert::assertEquals($expectedValue, $this->lastExternalStorageData[$expectedField], "Field '$expectedField' does not match ({$this->lastExternalStorageData[$expectedField]})"); + } + } + + private function sendJsonWithRequestToken(string $method, string $url, TableNode $fields): void { + $isFirstField = true; + $fieldsAsJsonString = '{'; + foreach ($fields->getRowsHash() as $key => $value) { + $fieldsAsJsonString .= ($isFirstField ? '' : ',') . '"' . $key . '":' . $value; + $isFirstField = false; + } + $fieldsAsJsonString .= '}'; + + $body = [ + 'headers' => [ + 'Content-Type' => 'application/json', + ], + 'body' => $fieldsAsJsonString, + ]; + $this->sendingAToWithRequesttoken($method, $url, $body); + } +} diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 638772da0b7e6..893dc3094bacc 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -15,6 +15,7 @@ */ class FeatureContext implements Context, SnippetAcceptingContext { use ContactsMenu; + use ExternalStorage; use Search; use WebDav; use Trashbin; diff --git a/build/integration/files_features/external-storage.feature b/build/integration/files_features/external-storage.feature index 111b5686e0e6e..134b8c54c73e9 100644 --- a/build/integration/files_features/external-storage.feature +++ b/build/integration/files_features/external-storage.feature @@ -63,3 +63,33 @@ Feature: external-storage Then as "user1" the file "/local_storage/foo2/textfile0.txt" does not exist And as "user0" the file "/local_storage/foo2/textfile0.txt" does not exist And as "user1" the file "/local.txt" exists + + + + Scenario: Save an external storage with password provided by user + Given Logging in using web as "admin" + And logged in user creates external global storage + | mountPoint | "ExternalStorageTest" | + | backend | "owncloud" | + | authMechanism | "password::userprovided" | + | backendOptions | {"host":"http://localhost:8080","secure":false} | + And fields of last external storage match with + | status | 2 | + When logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"admin"} | + Then fields of last external storage match with + | status | 0 | + + Scenario: Save an external storage with global credentials provided by user + Given Logging in using web as "admin" + And logged in user creates external global storage + | mountPoint | "ExternalStorageTest" | + | backend | "owncloud" | + | authMechanism | "password::global::user" | + | backendOptions | {"host":"http://localhost:8080","secure":false} | + And fields of last external storage match with + | status | 2 | + When logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"admin"} | + Then fields of last external storage match with + | status | 0 | diff --git a/build/integration/run.sh b/build/integration/run.sh index cef59c976af21..8f5320af8f5f7 100755 --- a/build/integration/run.sh +++ b/build/integration/run.sh @@ -41,7 +41,7 @@ echo $PORT echo "" > phpserver.log -php -S localhost:$PORT -t ../.. &> phpserver.log & +PHP_CLI_SERVER_WORKERS=2 php -S localhost:$PORT -t ../.. &> phpserver.log & PHPPID=$! echo $PHPPID