Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POC][tests-only] add endpoints to accept ocis commands #9546

Merged
merged 14 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .drone.star
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ config = {
"OCM_OCM_PROVIDER_AUTHORIZER_PROVIDERS_FILE": "%s" % dirs["ocmProviders"],
},
},
"cli": {
"suites": [
"cliCommands",
],
"skip": False,
},
},
"apiTests": {
"numberOfParts": 10,
Expand Down Expand Up @@ -859,7 +865,7 @@ def localApiTestPipeline(ctx):
pipeline = {
"kind": "pipeline",
"type": "docker",
"name": "localApiTests-%s-%s" % (suite, storage),
"name": "%s-Tests-%s-%s" % ("CLI" if name.startswith("cli") else "API", suite, storage),
"platform": {
"os": "linux",
"arch": "amd64",
Expand Down
45 changes: 45 additions & 0 deletions tests/TestHelpers/CliHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php declare(strict_types=1);
/**
* ownCloud
*
* @author Sajan Gurung <[email protected]>
* @copyright Copyright (c) 2024 Sajan Gurung [email protected]
*
* 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/>
*
*/

namespace TestHelpers;

use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Psr7\Request;
use Psr\Http\Message\ResponseInterface;
use TestHelpers\OcisConfigHelper;

/**
* A helper class for running oCIS CLI commands
*/
class CliHelper {
/**
* @param array $body
*
* @return ResponseInterface
* @throws GuzzleException
*/
public static function runCommand(array $body): ResponseInterface {
$url = OcisConfigHelper::getWrapperUrl() . "/command";
return OcisConfigHelper::sendRequest($url, "POST", \json_encode($body));
}
}
30 changes: 28 additions & 2 deletions tests/TestHelpers/OcisConfigHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class OcisConfigHelper {
* @return ResponseInterface
* @throws GuzzleException
*/
private static function sendRequest(
public static function sendRequest(
string $url,
string $method,
?string $body = ""
Expand All @@ -54,10 +54,18 @@ private static function sendRequest(
);

try {
return $client->send($request);
$response = $client->send($request);
} catch (ConnectException $e) {
throw new \Error("Cannot connect to the ociswrapper at the moment, make sure that ociswrapper is running before proceeding with the test run.\n" . $e->getMessage());
} catch (GuzzleException $ex) {
$response = $ex->getResponse();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WHat will it throw if it's GuzzleException and response is not null?

Copy link
Member Author

@saw-jan saw-jan Jul 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will not throw but returns the response


if ($response === null) {
throw $ex;
}
}

return $response;
}

/**
Expand Down Expand Up @@ -90,4 +98,22 @@ public static function rollbackOcis(): ResponseInterface {
$url = self::getWrapperUrl() . "/rollback";
return self::sendRequest($url, "DELETE");
}

/**
* @return ResponseInterface
* @throws GuzzleException
*/
public static function stopOcis(): ResponseInterface {
$url = self::getWrapperUrl() . "/stop";
return self::sendRequest($url, "POST");
}

/**
* @return ResponseInterface
* @throws GuzzleException
*/
public static function startOcis(): ResponseInterface {
$url = self::getWrapperUrl() . "/start";
return self::sendRequest($url, "POST");
}
}
8 changes: 8 additions & 0 deletions tests/acceptance/config/behat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,14 @@ default:
- SharingNgContext:
- SpacesContext:

cliCommands:
paths:
- "%paths.base%/../features/cliCommands"
context: *common_ldap_suite_context
contexts:
- FeatureContext: *common_feature_context_params
- CliContext:

extensions:
rdx\behatvars\BehatVariablesExtension: ~

Expand Down
122 changes: 122 additions & 0 deletions tests/acceptance/features/bootstrap/CliContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?php declare(strict_types=1);
/**
* ownCloud
*
* @author Sajan Gurung <[email protected]>
* @copyright Copyright (c) 2024 Sajan Gurung [email protected]
*
* 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 PHPUnit\Framework\Assert;
use Psr\Http\Message\ResponseInterface;
use TestHelpers\CliHelper;
use TestHelpers\OcisConfigHelper;

/**
* CLI context
*/
class CliContext implements Context {
private FeatureContext $featureContext;

/**
* @BeforeScenario
*
* @param BeforeScenarioScope $scope
*
* @return void
*/
public function setUpScenario(BeforeScenarioScope $scope): void {
// Get the environment
$environment = $scope->getEnvironment();
// Get all the contexts you need in this context
$this->featureContext = $environment->getContext('FeatureContext');
}

/**
* @Given the administrator has stopped the server
*
* @return void
*/
public function theAdministratorHasStoppedTheServer(): void {
$response = OcisConfigHelper::stopOcis();
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
}

/**
* @Given the administrator has started the server
*
* @return void
*/
public function theAdministratorHasStartedTheServer(): void {
$response = OcisConfigHelper::startOcis();
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
}

/**
* @When the administrator resets the password of user :user to :password using the CLI
*
* @param string $user
* @param string $password
*
* @return void
*/
public function theAdministratorResetsThePasswordOfUserUsingTheCLI(string $user, string $password): void {
$command = "idm resetpassword -u $user";
$body = [
"command" => $command,
"inputs" => [$password, $password]
];

$this->featureContext->setResponse(CliHelper::runCommand($body));
$this->featureContext->updateUserPassword($user, $password);
}

/**
* @Then the command should be successful
*
* @return void
*/
public function theCommandShouldBeSuccessful(): void {
$response = $this->featureContext->getResponse();
$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"]);
}

/**
* @Then /^the command output (should|should not) contain "([^"]*)"$/
*
* @param string $shouldOrNot
* @param string $output
*
* @return void
*/
public function theCommandOutputShouldContain(string $shouldOrNot, string $output): void {
$response = $this->featureContext->getResponse();
$jsonResponse = $this->featureContext->getJsonDecodedResponse($response);

if ($shouldOrNot === "should") {
Assert::assertStringContainsString($output, $jsonResponse["message"]);
} else {
Assert::assertStringNotContainsString($output, $jsonResponse["message"]);
}
}
}
35 changes: 35 additions & 0 deletions tests/acceptance/features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
use TestHelpers\GraphHelper;
use TestHelpers\WebDavHelper;
use TestHelpers\SettingsHelper;
use TestHelpers\OcisConfigHelper;

require_once 'bootstrap.php';

Expand Down Expand Up @@ -655,6 +656,22 @@ public static function logStep(BeforeStepScope $scope): void {
HttpLogger::writeLog(HttpLogger::getScenarioLogPath(), $logMessage);
}

/**
* FIRST AfterScenario HOOK
*
* NOTE: This method is called after each scenario having the @env-config tag
* This ensures that the server is running for clean-up purposes
*
* @AfterScenario @env-config
*
* @return void
*/
public function startOcisServer(): void {
$response = OcisConfigHelper::startOcis();
// 409 is returned if the server is already running
$this->theHTTPStatusCodeShouldBe([200, 409], 'Starting oCIS server', $response);
}

/**
* Get the externally-defined admin username, if any
*
Expand Down Expand Up @@ -1695,6 +1712,24 @@ public function getPasswordForUser(?string $userName): string {
return (string)$this->getActualPassword($this->regularUserPassword);
}

/**
* @param string $username
* @param string $password
*
* @return void
* @throws Exception
*/
public function updateUserPassword(string $username, string $password): void {
$username = $this->normalizeUsername($username);
if ($username === $this->getAdminUsername()) {
$this->adminPassword = $password;
} elseif (\array_key_exists($username, $this->createdUsers)) {
$this->createdUsers[$username]['password'] = $password;
} else {
throw new Exception("User '$username' not found");
}
}

/**
* Get the display name of the user.
*
Expand Down
50 changes: 48 additions & 2 deletions tests/acceptance/features/bootstrap/WebDav.php
Original file line number Diff line number Diff line change
Expand Up @@ -443,12 +443,13 @@ public function makeDavRequest(
* @param string $user
* @param string $folder
* @param bool|null $isGivenStep
* @param string|null $password
*
* @return ResponseInterface
* @throws JsonException | GuzzleException
* @throws GuzzleException | JsonException
*/
public function createFolder(string $user, string $folder, ?bool $isGivenStep = false): ResponseInterface {
public function createFolder(string $user, string $folder, ?bool $isGivenStep = false, ?string $password = null): ResponseInterface {
$folder = '/' . \ltrim($folder, '/');
return $this->makeDavRequest(
$user,
Expand All @@ -459,7 +460,7 @@ public function createFolder(string $user, string $folder, ?bool $isGivenStep =
"files",
null,
false,
null,
$password,
[],
null,
$isGivenStep
Expand Down Expand Up @@ -3349,6 +3350,31 @@ public function userShouldBeAbleToCreateFolder(string $user, string $destination
);
}

/**
* @Then user :user should be able to create folder :destination using password :password
*
* @param string $user
* @param string $destination
* @param string $password
*
* @return void
* @throws Exception
*/
public function userShouldBeAbleToCreateFolderUsingPassword(string $user, string $destination, string $password):void {
$user = $this->getActualUsername($user);
$response = $this->createFolder($user, $destination, true, $password);
$this->theHTTPStatusCodeShouldBe(
["201", "204"],
"HTTP status code was not 201 or 204 while trying to create folder '$destination' for user '$user'",
$response
);
$this->checkFileOrFolderExistsForUser(
$user,
"folder",
$destination
);
}

/**
* @Then user :user should not be able to create folder :destination
*
Expand All @@ -3369,6 +3395,26 @@ public function userShouldNotBeAbleToCreateFolder(string $user, string $destinat
);
}

/**
* @Then user :user should not be able to create folder :destination using password :password
*
* @param string $user
* @param string $destination
* @param string $password
*
* @return void
* @throws Exception
*/
public function userShouldNotBeAbleToCreateFolderUsingPassword(string $user, string $destination, string $password):void {
$user = $this->getActualUsername($user);
$response = $this->createFolder($user, $destination, false, $password);
$this->theHTTPStatusCodeShouldBeBetween(400, 499, $response);
$this->checkFileOrFolderDoesNotExistsForUser(
$user,
"folder",
$destination
);
}
/**
* Old style chunking upload
*
Expand Down
Loading