mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-09-29 07:29:43 -04:00
The AfterScenario hook only asserted that the clean command returned 200, but cleaning sessions happens asynchronously in the daemon. Poll the session list until it is empty (60s deadline) so leftover sessions do not leak into the next scenario.
1354 lines
41 KiB
PHP
1354 lines
41 KiB
PHP
<?php declare(strict_types=1);
|
|
/**
|
|
* @author Sajan Gurung <sajan@jankaritech.com>
|
|
* @copyright Copyright (c) 2024 Sajan Gurung sajan@jankaritech.com
|
|
*
|
|
* This code is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License,
|
|
* as published by the Free Software Foundation;
|
|
* either version 3 of the License, or any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
*
|
|
*/
|
|
|
|
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
|
use Behat\Behat\Context\Context;
|
|
use Behat\Gherkin\Node\TableNode;
|
|
use PHPUnit\Framework\Assert;
|
|
use TestHelpers\CliHelper;
|
|
use TestHelpers\OcConfigHelper;
|
|
use TestHelpers\BehatHelper;
|
|
use Psr\Http\Message\ResponseInterface;
|
|
use Behat\Step\Given;
|
|
use Behat\Step\Then;
|
|
use Behat\Step\When;
|
|
|
|
/**
|
|
* CLI context
|
|
*/
|
|
class CliContext implements Context {
|
|
private FeatureContext $featureContext;
|
|
private SpacesContext $spacesContext;
|
|
|
|
/**
|
|
* opencloud storage root path (with $HOME/~ expanded for CI)
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getStorageRootPath(): string {
|
|
$path = getenv('OC_STORAGE_PATH') ?: '/var/lib/opencloud/storage/users';
|
|
// need for CI
|
|
$home = getenv('HOME');
|
|
$path = preg_replace('#^~/#', $home . '/', $path);
|
|
$path = str_replace('$HOME', $home, $path);
|
|
|
|
return rtrim($path, '/');
|
|
}
|
|
|
|
/**
|
|
* opencloud users storage path
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getUsersStoragePath(): string {
|
|
return self::getStorageRootPath() . '/users';
|
|
}
|
|
|
|
/**
|
|
* opencloud project spaces storage path
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getProjectsStoragePath(): string {
|
|
return self::getStorageRootPath() . '/projects';
|
|
}
|
|
|
|
/**
|
|
* @BeforeScenario
|
|
*
|
|
* @param BeforeScenarioScope $scope
|
|
*
|
|
* @return void
|
|
*/
|
|
public function before(BeforeScenarioScope $scope): void {
|
|
// Get the environment
|
|
$environment = $scope->getEnvironment();
|
|
// Get all the contexts you need in this context
|
|
$this->featureContext = BehatHelper::getContext($scope, $environment, 'FeatureContext');
|
|
$this->spacesContext = BehatHelper::getContext($scope, $environment, 'SpacesContext');
|
|
}
|
|
|
|
/**
|
|
* expects a file to exist at the given path
|
|
*
|
|
* @param string $path
|
|
* @param string|null $sizeGb
|
|
* @param int $maxSeconds
|
|
*
|
|
* @return void
|
|
*/
|
|
private function waitForPath(string $path, ?string $sizeGb = null, int $maxSeconds = 10): void {
|
|
$escapedPath = escapeshellarg($path);
|
|
|
|
for ($i = 0; $i < $maxSeconds * 5; $i++) {
|
|
if ($sizeGb) {
|
|
if (!preg_match('/^(\d+)gb$/i', $sizeGb, $matches)) {
|
|
throw new \InvalidArgumentException("Invalid size format: $sizeGb. Use formats like 1gb, 5gb.");
|
|
}
|
|
$targetBytes = (int)$matches[1] * 1024 * 1024 * 1024;
|
|
$body = [
|
|
"command" => "[ -f $escapedPath ] && stat -c%s $escapedPath || echo 0",
|
|
"raw" => true
|
|
];
|
|
$data = json_decode((string)CliHelper::runCommand($body)->getBody(), true);
|
|
|
|
if (isset($data['message']) && (int)trim($data['message']) >= $targetBytes) {
|
|
return;
|
|
}
|
|
} else {
|
|
$body = [
|
|
"command" => "ls $escapedPath >/dev/null 2>&1 && echo exists || echo not_exists",
|
|
"raw" => true
|
|
];
|
|
$response = CliHelper::runCommand($body);
|
|
$data = json_decode((string)$response->getBody(), true);
|
|
|
|
if (isset($data['message']) && trim($data['message']) === 'exists') {
|
|
return;
|
|
}
|
|
}
|
|
usleep(200000);
|
|
}
|
|
|
|
throw new \Exception("Timeout waiting for: $path");
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[Given('the administrator has stopped the server')]
|
|
public function theAdministratorHasStoppedTheServer(): void {
|
|
$response = OcConfigHelper::stopOpencloud();
|
|
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[Given('/^the administrator (?:starts|has started) the server$/')]
|
|
public function theAdministratorHasStartedTheServer(): void {
|
|
$response = OcConfigHelper::startOpencloud();
|
|
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $status
|
|
* @param string $user
|
|
* @param string $password
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('/^the administrator resets the password of (non-existing|existing) user "([^"]*)" to "([^"]*)" using the CLI$/')]
|
|
public function theAdministratorResetsThePasswordOfUserUsingTheCLI(
|
|
string $status,
|
|
string $user,
|
|
string $password
|
|
): void {
|
|
$command = "idm resetpassword -u $user";
|
|
$body = [
|
|
"command" => $command,
|
|
"inputs" => [$password, $password]
|
|
];
|
|
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
if ($status === "non-existing") {
|
|
return;
|
|
}
|
|
$this->featureContext->updateUserPassword($user, $password);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator deletes the empty trashbin folders using the CLI')]
|
|
public function theAdministratorDeletesEmptyTrashbinFoldersUsingTheCli(): void {
|
|
$path = $this->featureContext->getStorageUsersRoot();
|
|
$command = "trash purge-empty-dirs -p $path --dry-run=false";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator checks the backup consistency using the CLI')]
|
|
public function theAdministratorChecksTheBackupConsistencyUsingTheCli(): void {
|
|
$path = $this->featureContext->getStorageUsersRoot();
|
|
$command = "backup consistency -p $path";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $user
|
|
* @param string $expirationTime
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator creates app token for user :user with expiration time :expirationTime using the auth-app CLI')]
|
|
public function theAdministratorCreatesAppTokenForUserWithExpirationTimeUsingTheAuthAppCLI(
|
|
string $user,
|
|
string $expirationTime
|
|
): void {
|
|
$user = $this->featureContext->getActualUserName($user);
|
|
$command = "auth-app create --user-name=$user --expiration=$expirationTime";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $user
|
|
* @param string $expirationTime
|
|
*
|
|
* @return void
|
|
*/
|
|
#[Given('user :user has created app token with expiration time :expirationTime using the auth-app CLI')]
|
|
public function userHasCreatedAppTokenWithExpirationTimeUsingTheAuthAppCLI(
|
|
string $user,
|
|
string $expirationTime
|
|
): void {
|
|
$user = $this->featureContext->getActualUserName($user);
|
|
$command = "auth-app create --user-name=$user --expiration=$expirationTime";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
|
|
$response = CliHelper::runCommand($body);
|
|
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
|
$jsonResponse = $this->featureContext->getJsonDecodedResponse($response);
|
|
Assert::assertSame("OK", $jsonResponse["status"]);
|
|
Assert::assertSame(
|
|
0,
|
|
$jsonResponse["exitCode"],
|
|
"Expected exit code to be 0, but got " . $jsonResponse["exitCode"]
|
|
);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator removes all the file versions using the CLI')]
|
|
public function theAdministratorRemovesAllVersionsOfResources() {
|
|
$path = $this->featureContext->getStorageUsersRoot();
|
|
$command = "revisions purge -p $path --dry-run=false";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $file
|
|
* @param string $user
|
|
* @param string $space
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator removes the versions of file :file of user :user from space :space using the CLI')]
|
|
public function theAdministratorRemovesTheVersionsOfFileUsingFileId($file, $user, $space) {
|
|
$path = $this->featureContext->getStorageUsersRoot();
|
|
$fileId = $this->spacesContext->getFileId($user, $space, $file);
|
|
$command = "revisions purge -p $path -r $fileId --dry-run=false";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator reindexes all spaces using the CLI')]
|
|
public function theAdministratorReindexesAllSpacesUsingTheCli(): void {
|
|
$endpoint = $this->featureContext->getBaseUrlHostName();
|
|
$command = "search index --all-spaces --endpoint $endpoint:9220 --insecure";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $spaceName
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator reindexes a space :spaceName using the CLI')]
|
|
public function theAdministratorReindexesASpaceUsingTheCli(string $spaceName): void {
|
|
$spaceId = $this->spacesContext->getSpaceIdByName($this->featureContext->getAdminUsername(), $spaceName);
|
|
$endpoint = $this->featureContext->getBaseUrlHostName();
|
|
$command = "search index --space $spaceId --endpoint $endpoint:9220 --insecure";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $space
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator removes the file versions of space :space using the CLI')]
|
|
public function theAdministratorRemovesTheVersionsOfFilesInSpaceUsingSpaceId(string $space): void {
|
|
$path = $this->featureContext->getStorageUsersRoot();
|
|
$adminUsername = $this->featureContext->getAdminUsername();
|
|
$spaceId = $this->spacesContext->getSpaceIdByName($adminUsername, $space);
|
|
$command = "revisions purge -p $path -r $spaceId --dry-run=false";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator purges the expired trash-bin items using the CLI')]
|
|
public function theAdministratorPurgesExpiredTrashBinItemsUsingTheCli(): void {
|
|
$command = "storage-users trash-bin purge-expired";
|
|
$body = [
|
|
"command" => $command,
|
|
"timeout" => 15
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $space
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator lists the trash-bin items of space :space using the CLI')]
|
|
public function theAdministratorListsTrashBinItemsOfSpaceUsingTheCli(string $space): void {
|
|
$adminUsername = $this->featureContext->getAdminUsername();
|
|
$spaceId = $this->spacesContext->getSpaceIdByName($adminUsername, $space);
|
|
$command = "storage-users trash-bin list $spaceId";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator lists the trash-bin items of the personal space of user :user using the CLI')]
|
|
public function theAdministratorListsTrashBinItemsOfPersonalSpaceUsingTheCli(string $user): void {
|
|
$spaceId = $this->spacesContext->getSpaceIdByName($user, 'Personal');
|
|
$command = "storage-users trash-bin list $spaceId";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $space
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator restores all the trash-bin items of space :space using the CLI')]
|
|
public function theAdministratorRestoresAllTrashBinItemsOfSpaceUsingTheCli(string $space): void {
|
|
$adminUsername = $this->featureContext->getAdminUsername();
|
|
$spaceId = $this->spacesContext->getSpaceIdByName($adminUsername, $space);
|
|
$command = "storage-users trash-bin restore-all $spaceId --yes";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator restores all the trash-bin items of the personal space of user :user using the CLI')]
|
|
public function theAdministratorRestoresAllTrashBinItemsOfPersonalSpaceUsingTheCli(string $user): void {
|
|
$spaceId = $this->spacesContext->getSpaceIdByName($user, 'Personal');
|
|
$command = "storage-users trash-bin restore-all $spaceId --yes";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $fileId
|
|
* @param string $space
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator restores the trash-bin item with file-id :fileId of space :space using the CLI')]
|
|
public function theAdministratorRestoresTrashBinItemOfSpaceUsingTheCli(string $fileId, string $space): void {
|
|
$adminUsername = $this->featureContext->getAdminUsername();
|
|
$spaceId = $this->spacesContext->getSpaceIdByName($adminUsername, $space);
|
|
$command = "storage-users trash-bin restore $spaceId $fileId";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $fileId
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator restores the trash-bin item with file-id :fileId of the personal space of user :user using the CLI')]
|
|
public function theAdministratorRestoresTrashBinItemOfPersonalSpaceUsingTheCli(string $fileId, string $user): void {
|
|
$spaceId = $this->spacesContext->getSpaceIdByName($user, 'Personal');
|
|
$command = "storage-users trash-bin restore $spaceId $fileId";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator cleans up orphaned shares using the CLI')]
|
|
public function theAdministratorCleansUpOrphanedSharesUsingTheCli(): void {
|
|
$serviceAccountId = getenv('OC_SERVICE_ACCOUNT_ID') ?: 'service-account-id';
|
|
$serviceAccountSecret = getenv('OC_SERVICE_ACCOUNT_SECRET') ?: 'service-account-secret';
|
|
$command = "shares cleanup --service-account-id=$serviceAccountId"
|
|
. " --service-account-secret=$serviceAccountSecret";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator lists the unified roles using the CLI')]
|
|
public function theAdministratorListsTheUnifiedRolesUsingTheCli(): void {
|
|
$command = "graph list-unified-roles";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[Then('the command should be successful')]
|
|
public function theCommandShouldBeSuccessful(): void {
|
|
$response = $this->featureContext->getResponse();
|
|
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
|
|
|
$jsonResponse = $this->featureContext->getJsonDecodedResponse($response);
|
|
|
|
Assert::assertSame("OK", $jsonResponse["status"], $jsonResponse["message"]);
|
|
Assert::assertSame(
|
|
0,
|
|
$jsonResponse["exitCode"],
|
|
"Expected exit code to be 0, but got " . $jsonResponse["exitCode"]
|
|
. ". Message: " . $jsonResponse["message"]
|
|
);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $shouldOrNot
|
|
* @param string $output
|
|
*
|
|
* @return void
|
|
*/
|
|
#[Then('/^the command output (should|should not) contain "([^"]*)"$/')]
|
|
public function theCommandOutputShouldContain(string $shouldOrNot, string $output): void {
|
|
$response = $this->featureContext->getResponse();
|
|
$jsonResponse = $this->featureContext->getJsonDecodedResponse($response);
|
|
$output = $this->featureContext->substituteInLineCodes($output);
|
|
|
|
if ($shouldOrNot === "should") {
|
|
Assert::assertStringContainsString($output, $jsonResponse["message"]);
|
|
} else {
|
|
Assert::assertStringNotContainsString($output, $jsonResponse["message"]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string|null $flag
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator lists all the upload sessions')]
|
|
#[When('the administrator lists all the upload sessions with flag :flag')]
|
|
public function theAdministratorListsAllTheUploadSessions(?string $flag = null): void {
|
|
if ($flag) {
|
|
$flag = "--$flag";
|
|
}
|
|
$command = "storage-users uploads sessions --json $flag";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param TableNode $table
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator cleans upload sessions with the following flags:')]
|
|
public function theAdministratorCleansUploadSessionsWithTheFollowingFlags(TableNode $table): void {
|
|
$flag = "";
|
|
foreach ($table->getRows() as $row) {
|
|
$flag .= "--$row[0] ";
|
|
}
|
|
$flagString = trim($flag);
|
|
$command = "storage-users uploads sessions $flagString --clean --json";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator restarts the upload sessions that are in postprocessing')]
|
|
public function theAdministratorRestartsTheUploadSessionsThatAreInPostprocessing(): void {
|
|
$command = "storage-users uploads sessions --processing --restart --json";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $file
|
|
*
|
|
* @return void
|
|
* @throws JsonException
|
|
*/
|
|
#[When('the administrator restarts the upload sessions of file :file')]
|
|
public function theAdministratorRestartsUploadSessionsOfFile(string $file): void {
|
|
$response = CliHelper::runCommand(["command" => "storage-users uploads sessions --json"]);
|
|
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
|
$responseArray = $this->getJSONDecodedCliMessage($response);
|
|
|
|
foreach ($responseArray as $item) {
|
|
if ($item->filename === $file) {
|
|
$uploadId = $item->id;
|
|
}
|
|
}
|
|
|
|
$command = "storage-users uploads sessions --id=$uploadId --restart --json";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $shouldOrNot
|
|
* @param TableNode $table
|
|
*
|
|
* @return void
|
|
* @throws JsonException
|
|
*/
|
|
#[Then('/^the CLI response (should|should not) contain these entries:$/')]
|
|
public function theCLIResponseShouldContainTheseEntries(string $shouldOrNot, TableNode $table): void {
|
|
$expectedFiles = $table->getColumn(0);
|
|
$responseArray = $this->getJSONDecodedCliMessage($this->featureContext->getResponse());
|
|
|
|
$resourceNames = [];
|
|
foreach ($responseArray as $item) {
|
|
if (isset($item->filename)) {
|
|
$resourceNames[] = $item->filename;
|
|
}
|
|
}
|
|
|
|
if ($shouldOrNot === "should not") {
|
|
foreach ($expectedFiles as $expectedFile) {
|
|
Assert::assertNotTrue(
|
|
\in_array($expectedFile, $resourceNames),
|
|
"The resource '$expectedFile' was found in the response."
|
|
);
|
|
}
|
|
} else {
|
|
foreach ($expectedFiles as $expectedFile) {
|
|
Assert::assertTrue(
|
|
\in_array($expectedFile, $resourceNames),
|
|
"The resource '$expectedFile' was not found in the response."
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param ResponseInterface $response
|
|
*
|
|
* @return array
|
|
* @throws JsonException
|
|
*/
|
|
public function getJSONDecodedCliMessage(ResponseInterface $response): array {
|
|
$responseBody = $this->featureContext->getJsonDecodedResponse($response);
|
|
|
|
// $responseBody["message"] contains a message info with the array of output json of the upload sessions command
|
|
// Example Output: "INFO memory is not limited, skipping package=github.com/KimMachineGun/automemlimit/memlimit [{<output-json>}]"
|
|
// So, only extracting the array of output json from the message
|
|
\preg_match('/(\[.*\])/', $responseBody["message"], $matches);
|
|
return \json_decode($matches[1], null, 512, JSON_THROW_ON_ERROR);
|
|
}
|
|
|
|
/**
|
|
* @AfterScenario @cli-uploads-sessions
|
|
*
|
|
* @return void
|
|
* @throws JsonException
|
|
*/
|
|
public function cleanUploadsSessions(): void {
|
|
$command = "storage-users uploads sessions --clean";
|
|
$body = [
|
|
"command" => $command
|
|
];
|
|
$response = CliHelper::runCommand($body);
|
|
Assert::assertEquals("200", $response->getStatusCode(), "Failed to clean upload sessions");
|
|
|
|
// Cleaning upload sessions happens asynchronously in the daemon, so wait
|
|
// until all sessions are actually gone. Otherwise leftover sessions would
|
|
// leak into the next scenario.
|
|
$deadline = \time() + 60;
|
|
$sessions = $this->listUploadSessions();
|
|
while (count($sessions) > 0 && \time() < $deadline) {
|
|
\sleep(1);
|
|
$sessions = $this->listUploadSessions();
|
|
}
|
|
$sessionNames = \array_map(
|
|
static fn ($session) => $session->filename ?? "?",
|
|
$sessions
|
|
);
|
|
Assert::assertCount(
|
|
0,
|
|
$sessions,
|
|
"Upload sessions were not cleaned up in time: " . \json_encode($sessionNames)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Lists all upload sessions via the CLI.
|
|
*
|
|
* @return array
|
|
* @throws JsonException
|
|
*/
|
|
private function listUploadSessions(): array {
|
|
$response = CliHelper::runCommand(["command" => "storage-users uploads sessions --json"]);
|
|
Assert::assertEquals("200", $response->getStatusCode(), "Failed to list upload sessions");
|
|
return $this->getJSONDecodedCliMessage($response);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $folder
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator creates the folder :folder for user :user on the POSIX filesystem')]
|
|
public function theAdministratorCreatesFolder(string $folder, string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$fullPath = "$storagePath/$userUuid/$folder";
|
|
|
|
$body = [
|
|
"command" => "mkdir -p $fullPath",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
$this->waitForPath($fullPath);
|
|
sleep(1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator lists the content of the POSIX storage folder of user :user')]
|
|
public function theAdministratorCheckUsersFolder(string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$body = [
|
|
"command" => "ls -la $storagePath/$userUuid",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $file
|
|
* @param string $content
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator creates the file :file with content :content for user :user on the POSIX filesystem')]
|
|
public function theAdministratorCreatesFile(string $file, string $content, string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$fullPath = "$storagePath/$userUuid/$file";
|
|
$safeContent = escapeshellarg($content);
|
|
$body = [
|
|
"command" => "echo -n $safeContent > $fullPath",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
$this->waitForPath($fullPath);
|
|
sleep(1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $file
|
|
* @param string $content
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator has created the file :file with content :content for user :user on the POSIX filesystem')]
|
|
public function theAdministratorHasCreatedFile(string $file, string $content, string $user): void {
|
|
$this->theAdministratorCreatesFile($file, $content, $user);
|
|
$this->theCommandShouldBeSuccessful();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $file
|
|
* @param string $size Example: "1gb", "5gb"
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator creates the file :file with size :size for user :user on the POSIX filesystem')]
|
|
public function theAdministratorCreatesLargeFileWithSize(string $file, string $size, string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
|
|
$size = strtolower($size);
|
|
if (!preg_match('/^(\d+)gb$/', $size, $matches)) {
|
|
throw new \InvalidArgumentException("Invalid size format: $size. Use formats like 1gb, 5gb.");
|
|
}
|
|
|
|
$count = (int)$matches[1] * 1024; // 1GB = 1024M
|
|
$bs = '1M';
|
|
$filePath = "$storagePath/$userUuid/$file";
|
|
|
|
$body = [
|
|
"command" => "dd if=/dev/zero of=$filePath bs=$bs count=$count",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
$this->waitForPath($filePath, $size, 15);
|
|
sleep(7);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param int $count
|
|
* @param string $dir
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator creates :count files sequentially in the directory :dir for user :user on the POSIX filesystem')]
|
|
public function theAdministratorCreatesFilesSequentially(int $count, string $dir, string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath() . "/$userUuid/$dir";
|
|
$cmd = '';
|
|
for ($i = 1; $i <= $count; $i++) {
|
|
$cmd .= "echo -n \"file $i content\" > $storagePath/file_$i.txt; ";
|
|
}
|
|
$body = [
|
|
"command" => $cmd,
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
$this->waitForPath("$storagePath/file_$count.txt");
|
|
sleep(3);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param int $count
|
|
* @param string $dir
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator creates :count files in parallel in the directory :dir for user :user on the POSIX filesystem')]
|
|
public function theAdministratorCreatesFilesInParallel(int $count, string $dir, string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath() . "/$userUuid/$dir";
|
|
$cmd = "mkdir -p $storagePath; ";
|
|
for ($i = 1; $i <= $count; $i++) {
|
|
$cmd .= "echo -n \"parallel file $i content\" > $storagePath/parallel_$i.txt & ";
|
|
}
|
|
$cmd .= "wait";
|
|
$body = [
|
|
"command" => $cmd,
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
$this->waitForPath("$storagePath/parallel_$count.txt");
|
|
sleep(1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $content
|
|
* @param string $file
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator puts the content :content into the file :file in the POSIX storage folder of user :user')]
|
|
public function theAdministratorChangesFileContent(string $content, string $file, string $user): void {
|
|
// this downloads the file using WebDAV and by that checks if it's still in
|
|
// postprocessing. So its effectively a check for finished postprocessing
|
|
$this->featureContext->userDownloadsFileUsingTheAPI($user, $file);
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$safeContent = escapeshellarg($content);
|
|
$body = [
|
|
"command" => "echo -n $safeContent >> $storagePath/$userUuid/$file",
|
|
"raw" => true
|
|
];
|
|
sleep(1);
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
sleep(1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $user
|
|
* @param string $file
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator reads the content of the file :file in the POSIX storage folder of user :user')]
|
|
public function theAdministratorReadsTheFileContent(string $user, string $file): void {
|
|
// this downloads the file using WebDAV and by that checks if it's still in
|
|
// postprocessing. So its effectively a check for finished postprocessing
|
|
$this->featureContext->userDownloadsFileUsingTheAPI($user, $file);
|
|
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$body = [
|
|
"command" => "cat $storagePath/$userUuid/$file",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $user
|
|
* @param string $file
|
|
* @param string $folder
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator copies the file :file to the folder :folder for user :user on the POSIX filesystem')]
|
|
public function theAdministratorCopiesFileToFolder(string $user, string $file, string $folder): void {
|
|
// this downloads the file using WebDAV and by that checks if it's still in
|
|
// postprocessing. So its effectively a check for finished postprocessing
|
|
$this->featureContext->userDownloadsFileUsingTheAPI($user, $file);
|
|
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
|
|
$source = "$storagePath/$userUuid/$file";
|
|
$destination = "$storagePath/$userUuid/$folder";
|
|
|
|
$body = [
|
|
"command" => "cp $source $destination",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
sleep(1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $user
|
|
* @param string $file
|
|
* @param string $newName
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator renames the file :file to :newName for user :user on the POSIX filesystem')]
|
|
public function theAdministratorRenamesFile(string $user, string $file, string $newName): void {
|
|
// this downloads the file using WebDAV and by that checks if it's still in
|
|
// postprocessing. So its effectively a check for finished postprocessing
|
|
$this->featureContext->userDownloadsFileUsingTheAPI($user, $file);
|
|
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
|
|
$source = "$storagePath/$userUuid/$file";
|
|
$destination = "$storagePath/$userUuid/$newName";
|
|
|
|
$body = [
|
|
"command" => "mv $source $destination",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
sleep(1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $user
|
|
* @param string $file
|
|
* @param string $folder
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator moves the file :file to the folder :folder for user :user on the POSIX filesystem')]
|
|
public function theAdministratorMovesFileToFolder(string $user, string $file, string $folder): void {
|
|
// this downloads the file using WebDAV and by that checks if it's still in
|
|
// postprocessing. So its effectively a check for finished postprocessing
|
|
$this->featureContext->userDownloadsFileUsingTheAPI($user, $file);
|
|
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
|
|
$source = "$storagePath/$userUuid/$file";
|
|
$destination = "$storagePath/$userUuid/$folder";
|
|
|
|
$body = [
|
|
"command" => "mv $source $destination",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
sleep(1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $file
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator deletes the file :file for user :user on the POSIX filesystem')]
|
|
public function theAdministratorDeletesFile(string $file, string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
|
|
$body = [
|
|
"command" => "rm $storagePath/$userUuid/$file",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
sleep(1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $folder
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator deletes the folder :folder for user :user on the POSIX filesystem')]
|
|
public function theAdministratorDeletesFolder(string $folder, string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
|
|
$body = [
|
|
"command" => "rm -r $storagePath/$userUuid/$folder",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
sleep(1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $user
|
|
* @param string $file
|
|
* @param string $space
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator copies the file :file to the space :space for user :user on the POSIX filesystem')]
|
|
public function theAdministratorCopiesFileToSpace(string $user, string $file, string $space): void {
|
|
// this downloads the file using WebDAV and by that checks if it's still in
|
|
// postprocessing. So its effectively a check for finished postprocessing
|
|
$this->featureContext->userDownloadsFileUsingTheAPI($user, $file);
|
|
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$usersStoragePath = $this->getUsersStoragePath();
|
|
$projectsStoragePath = $this->getProjectsStoragePath();
|
|
$spaceId = $this->spacesContext->getSpaceIdByName($this->featureContext->getAdminUsername(), $space);
|
|
$spaceId = explode('$', $spaceId)[1];
|
|
|
|
$source = "$usersStoragePath/$userUuid/$file";
|
|
$destination = "$projectsStoragePath/$spaceId";
|
|
|
|
$body = [
|
|
"command" => "cp $source $destination",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
sleep(1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $attribute
|
|
* @param string $file
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator checks the attribute :attribute of file :file for user :user on the POSIX filesystem')]
|
|
public function theAdminChecksTheAttributeOfFileForUser(string $attribute, string $file, string $user): void {
|
|
// this downloads the file using WebDAV and by that checks if it's still in
|
|
// postprocessing. So its effectively a check for finished postprocessing
|
|
$this->featureContext->userDownloadsFileUsingTheAPI($user, $file);
|
|
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$body = [
|
|
"command" => "getfattr -n " . escapeshellarg($attribute) . " --only-values $storagePath/$userUuid/$file",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
* on-disk path of a project space root
|
|
*
|
|
* @param string $space
|
|
*
|
|
* @return string
|
|
*/
|
|
private function getProjectSpaceStoragePath(string $space): string {
|
|
$spaceId = $this->spacesContext->getSpaceIdByName($this->featureContext->getAdminUsername(), $space);
|
|
$spaceId = explode('$', $spaceId)[1];
|
|
return $this->getProjectsStoragePath() . "/$spaceId";
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator scans the whole storage using the CLI')]
|
|
public function theAdministratorScansTheWholeStorageUsingTheCli(): void {
|
|
$body = [
|
|
"command" => "posixfs scan"
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $folder
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator scans the folder :folder of user :user using the CLI')]
|
|
public function theAdministratorScansTheFolderOfUserUsingTheCli(string $folder, string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$body = [
|
|
"command" => "posixfs scan $storagePath/$userUuid/$folder"
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $space
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator scans the space :space using the CLI')]
|
|
public function theAdministratorScansTheSpaceUsingTheCli(string $space): void {
|
|
$body = [
|
|
"command" => "posixfs scan " . $this->getProjectSpaceStoragePath($space)
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator checks the posixfs consistency using the CLI')]
|
|
public function theAdministratorChecksThePosixfsConsistencyUsingTheCli(): void {
|
|
$body = [
|
|
"command" => "posixfs consistency"
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $flag
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator checks the posixfs consistency using the CLI with flag :flag')]
|
|
public function theAdministratorChecksThePosixfsConsistencyUsingTheCliWithFlag(string $flag): void {
|
|
$body = [
|
|
"command" => "posixfs consistency $flag"
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $file
|
|
* @param string $content
|
|
* @param string $space
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator creates the file :file with content :content in the space :space on the POSIX filesystem')]
|
|
public function theAdministratorCreatesFileInSpaceOnPosix(string $file, string $content, string $space): void {
|
|
$fullPath = $this->getProjectSpaceStoragePath($space) . "/$file";
|
|
$safeContent = escapeshellarg($content);
|
|
$body = [
|
|
"command" => "echo -n $safeContent > $fullPath",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
$this->waitForPath($fullPath);
|
|
}
|
|
|
|
/**
|
|
* reads xattrs from disk with getfattr, bypassing the driver's on-the-fly assimilation
|
|
*
|
|
* @param string $file
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator gets the extended attributes of file :file of user :user on the POSIX filesystem')]
|
|
public function theAdministratorGetsExtendedAttributesOfFileOfUser(string $file, string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$body = [
|
|
"command" => "getfattr -d $storagePath/$userUuid/$file",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $file
|
|
* @param string $space
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator gets the extended attributes of file :file in the space :space on the POSIX filesystem')]
|
|
public function theAdministratorGetsExtendedAttributesOfFileInSpace(string $file, string $space): void {
|
|
$body = [
|
|
"command" => "getfattr -d " . $this->getProjectSpaceStoragePath($space) . "/$file",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $attribute
|
|
* @param string $file
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator gets the extended attribute :attribute of file :file of user :user on the POSIX filesystem')]
|
|
public function theAdministratorGetsExtendedAttributeOfFileOfUser(string $attribute, string $file, string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$body = [
|
|
"command" => "getfattr -n " . escapeshellarg($attribute) . " --only-values $storagePath/$userUuid/$file",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $attribute
|
|
* @param string $file
|
|
* @param string $user
|
|
* @param string $value
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator sets the extended attribute :attribute of file :file of user :user to :value on the POSIX filesystem')]
|
|
public function theAdministratorSetsExtendedAttributeOfFileOfUser(
|
|
string $attribute,
|
|
string $file,
|
|
string $user,
|
|
string $value
|
|
): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$body = [
|
|
"command" => "setfattr -n " . escapeshellarg($attribute)
|
|
. " -v " . escapeshellarg($value) . " $storagePath/$userUuid/$file",
|
|
"raw" => true
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $file
|
|
* @param string $user
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator scans the file :file of user :user using the CLI')]
|
|
public function theAdministratorScansTheFileOfUserUsingTheCli(string $file, string $user): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$body = [
|
|
"command" => "posixfs scan $storagePath/$userUuid/$file"
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $path
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator scans path :path using the CLI')]
|
|
public function theAdministratorScansPathUsingTheCli(string $path): void {
|
|
$body = [
|
|
"command" => "posixfs scan $path"
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
* non-existing path first, so with "-E" the scan aborts before the valid folder
|
|
*
|
|
* @param string $folder
|
|
* @param string $user
|
|
* @param string $flag
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator scans a non-existing path and the folder :folder of user :user using the CLI with flag :flag')]
|
|
public function theAdministratorScansNonExistingPathAndFolderUsingTheCli(
|
|
string $folder,
|
|
string $user,
|
|
string $flag
|
|
): void {
|
|
$userUuid = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
|
$storagePath = $this->getUsersStoragePath();
|
|
$nonExistingPath = "$storagePath/$userUuid/nonExistingPath";
|
|
$validPath = "$storagePath/$userUuid/$folder";
|
|
$flagPart = $flag !== "" ? "$flag " : "";
|
|
$body = [
|
|
"command" => "posixfs scan {$flagPart}$nonExistingPath $validPath"
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
#[Then('the command should not be successful')]
|
|
public function theCommandShouldNotBeSuccessful(): void {
|
|
$response = $this->featureContext->getResponse();
|
|
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
|
|
|
$jsonResponse = $this->featureContext->getJsonDecodedResponse($response);
|
|
|
|
Assert::assertNotSame(
|
|
0,
|
|
$jsonResponse["exitCode"],
|
|
"Expected command to fail with a non-zero exit code, but got 0. Message: " . $jsonResponse["message"]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param string $interval
|
|
*
|
|
* @return void
|
|
*/
|
|
#[When('the administrator sends the grouped :interval email notifications using the CLI')]
|
|
public function theAdministratorSendsTheGroupedEmailNotifications(string $interval): void {
|
|
$body = [
|
|
"command" => "notifications send-email --$interval"
|
|
];
|
|
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
|
$this->theCommandShouldBeSuccessful();
|
|
}
|
|
}
|