Skip to content

Commit

Permalink
test: Add integration tests for saving external userglobal storages
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
danxuliu committed Aug 7, 2024
1 parent 2fc56d9 commit 4bdddf2
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 2 deletions.
2 changes: 1 addition & 1 deletion build/integration/features/bootstrap/BasicStructure.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
103 changes: 103 additions & 0 deletions build/integration/features/bootstrap/ExternalStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
use Behat\Gherkin\Node\TableNode;
use PHPUnit\Framework\Assert;

require __DIR__ . '/../../vendor/autoload.php';

trait ExternalStorage {
private array $storageIds = [];

private array $lastExternalStorageData;

/**
* @AfterScenario
**/
public function deleteCreatedStorages(): void {
foreach ($this->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);
}
}
1 change: 1 addition & 0 deletions build/integration/features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
class FeatureContext implements Context, SnippetAcceptingContext {
use ContactsMenu;
use ExternalStorage;
use Search;
use WebDav;
use Trashbin;
Expand Down
30 changes: 30 additions & 0 deletions build/integration/files_features/external-storage.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
2 changes: 1 addition & 1 deletion build/integration/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 4bdddf2

Please sign in to comment.