[decomposed] more cli command tests (#3087)

* more cli command tests

* add tests to expected failures file
This commit is contained in:
Viktor Scharf
2026-07-09 07:51:43 +02:00
committed by GitHub
parent 415900ab01
commit 9efc71d42e
14 changed files with 364 additions and 26 deletions

View File

@@ -325,6 +325,150 @@ class CliContext implements Context {
$this->featureContext->setResponse(CliHelper::runCommand($body));
}
/**
* @When the administrator purges the expired trash-bin items using the CLI
*
* @return void
*/
public function theAdministratorPurgesExpiredTrashBinItemsUsingTheCli(): void {
$command = "storage-users trash-bin purge-expired";
$body = [
"command" => $command,
"timeout" => 15
];
$this->featureContext->setResponse(CliHelper::runCommand($body));
}
/**
* @When the administrator lists the trash-bin items of space :space using the CLI
*
* @param string $space
*
* @return void
*/
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));
}
/**
* @When the administrator lists the trash-bin items of the personal space of user :user using the CLI
*
* @param string $user
*
* @return void
*/
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));
}
/**
* @When the administrator restores all the trash-bin items of space :space using the CLI
*
* @param string $space
*
* @return void
*/
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));
}
/**
* @When the administrator restores all the trash-bin items of the personal space of user :user using the CLI
*
* @param string $user
*
* @return void
*/
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));
}
/**
* @When the administrator restores the trash-bin item with file-id :fileId of space :space using the CLI
*
* @param string $fileId
* @param string $space
*
* @return void
*/
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));
}
/**
* @When the administrator restores the trash-bin item with file-id :fileId of the personal space of user :user using the CLI
*
* @param string $fileId
* @param string $user
*
* @return void
*/
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));
}
/**
* @When the administrator cleans up orphaned shares using the CLI
*
* @return void
*/
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));
}
/**
* @When the administrator lists the unified roles using the CLI
*
* @return void
*/
public function theAdministratorListsTheUnifiedRolesUsingTheCli(): void {
$command = "graph list-unified-roles";
$body = [
"command" => $command
];
$this->featureContext->setResponse(CliHelper::runCommand($body));
}
/**
* @Then the command should be successful
*

View File

@@ -343,6 +343,12 @@ _ocdav: api compatibility, return correct status code_
- [apiSharingNg1/removeAccessToDrive.feature:145](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSharingNg1/removeAccessToDrive.feature#L145)
#### [POSIX: failing CLI commands](https://github.com/opencloud-eu/opencloud/issues/3095)
- [cliCommands/restoreTrashBinItems.feature:11](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/cliCommands/restoreTrashBinItems.feature#L11)
- [cliCommands/restoreTrashBinItems.feature:23](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/cliCommands/restoreTrashBinItems.feature#L23)
- [cliCommands/sharesCleanup.feature:12](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/cliCommands/sharesCleanup.feature#L12)
### Won't fix
Not everything needs to be implemented for opencloud.

View File

@@ -345,6 +345,14 @@ _ocdav: api compatibility, return correct status code_
- [apiSharingNg1/removeAccessToDrive.feature:145](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/apiSharingNg1/removeAccessToDrive.feature#L145)
tests/acceptance/features/cliCommands/restoreTrashBinItems.feature
#### [POSIX: failing CLI commands](https://github.com/opencloud-eu/opencloud/issues/3095)
- [cliCommands/restoreTrashBinItems.feature:11](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/cliCommands/restoreTrashBinItems.feature#L11)
- [cliCommands/restoreTrashBinItems.feature:23](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/cliCommands/restoreTrashBinItems.feature#L23)
- [cliCommands/sharesCleanup.feature:12](https://github.com/opencloud-eu/opencloud/blob/main/tests/acceptance/features/cliCommands/sharesCleanup.feature#L12)
### Won't fix

View File

@@ -1,4 +1,4 @@
@env-config
@env-config @skipOnOpencloud-posix-Storage
Feature: backup consistency
As a user
I want to check my data for inconsistencies

View File

@@ -1,24 +1,16 @@
@env-config
@env-config @skipOnOpencloud-posix-Storage
Feature: delete empty trash bin folder via CLI command
Scenario: delete empty trashbin folders
Given the user "Admin" has created a new user with the following attributes:
| userName | Alice |
| displayName | Alice Hansen |
| password | %alt1% |
Given user "Alice" has been created with default attributes
And user "Alice" has created the following folders
| path |
| folder-to-delete |
| folder-to-restore |
And user "Alice" has uploaded file with content "test file" to "testfile.txt"
And user "Alice" has deleted the following resources
| path |
| folder-to-delete |
| folder-to-restore |
| testfile.txt |
And user "Alice" has restored the folder with original path "folder-to-restore"
And user "Alice" has deleted the folder with original path "folder-to-delete" from the trashbin
And the administrator has stopped the server
When the administrator deletes the empty trashbin folders using the CLI
Then the command should be successful

View File

@@ -0,0 +1,13 @@
Feature: list unified roles via CLI command
As an admin
I want to list the available unified roles
So that I know their IDs when configuring GRAPH_AVAILABLE_ROLES or writing documentation
Scenario: list unified roles
When the administrator lists the unified roles using the CLI
Then the command should be successful
And the command output should contain "Viewer"
And the command output should contain "Editor"
And the command output should contain "SpaceManager"
And the command output should contain "SecureViewer"

View File

@@ -0,0 +1,28 @@
@env-config
Feature: list trash-bin items of a space via CLI command
As an admin
I want to list the trash-bin items of a space
So that I know which items are available to restore
Background:
Given user "Alice" has been created with default attributes
Scenario: list trash-bin items of a personal space
Given user "Alice" has uploaded file with content "some data" to "textfile.txt"
And user "Alice" has deleted file "textfile.txt"
When the administrator lists the trash-bin items of the personal space of user "Alice" using the CLI
Then the command should be successful
And the command output should contain "textfile.txt"
Scenario: list trash-bin items of a project space
Given using spaces DAV path
And the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API
And user "Alice" has created a space "new-space" with the default quota using the Graph API
And user "Alice" has uploaded a file inside space "new-space" with content "some data" to "textfile.txt"
And we save it into "FILEID"
And user "Alice" deletes file "textfile.txt" from space "new-space" using file-id "<<FILEID>>"
When the administrator lists the trash-bin items of space "new-space" using the CLI
Then the command should be successful
And the command output should contain "textfile.txt"

View File

@@ -0,0 +1,35 @@
@env-config
Feature: purge expired trash-bin items via CLI command
As an admin
I want to purge expired trash-bin items
So that the storage does not fill up with old deleted files
Background:
Given the following configs have been set:
| config | value |
| STORAGE_USERS_PURGE_TRASH_BIN_PERSONAL_DELETE_BEFORE | 1s |
| STORAGE_USERS_PURGE_TRASH_BIN_PROJECT_DELETE_BEFORE | 1s |
And user "Alice" has been created with default attributes
Scenario: purge expired trash-bin items of a personal space
Given user "Alice" has uploaded file with content "some data" to "textfile.txt"
And user "Alice" has deleted file "textfile.txt"
And the user waits for 2 seconds
When the administrator purges the expired trash-bin items using the CLI
Then the command should be successful
And user "Alice" lists the resources in the trashbin with depth "1" using the WebDAV API
And as "Alice" file "textfile.txt" should not exist in the trashbin of the space "Personal"
Scenario: purge expired trash-bin items of a project space
Given using spaces DAV path
And the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API
And user "Alice" has created a space "new-space" with the default quota using the Graph API
And user "Alice" has uploaded a file inside space "new-space" with content "some data" to "textfile.txt"
And we save it into "FILEID"
And user "Alice" deletes file "textfile.txt" from space "new-space" using file-id "<<FILEID>>"
And the user waits for 2 seconds
When the administrator purges the expired trash-bin items using the CLI
Then the command should be successful
And as "Alice" file "textfile.txt" should not exist in the trashbin of the space "new-space"

View File

@@ -1,4 +1,4 @@
@env-config
@env-config @skipOnOpencloud-posix-Storage
Feature: remove file versions via CLI command
Background:

View File

@@ -0,0 +1,67 @@
@env-config
Feature: restore trash-bin items via CLI command
As an admin
I want to restore a specific trash-bin item or all trash-bin items of a space
So that accidentally deleted files can be recovered individually or in bulk
Background:
Given user "Alice" has been created with default attributes
Scenario: restore a single trash-bin item of a personal space
Given user "Alice" has uploaded file with content "some data" to "textfile.txt"
And we save it into "FILEID"
And user "Alice" has deleted file "textfile.txt"
When the administrator restores the trash-bin item with file-id "<<FILEID>>" of the personal space of user "Alice" using the CLI
Then the command should be successful
And the command output should contain "textfile.txt"
When the administrator lists the trash-bin items of the personal space of user "Alice" using the CLI
Then the command should be successful
And the command output should contain "total count: 0"
Scenario: restore a single trash-bin item of a project space
Given using spaces DAV path
And the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API
And user "Alice" has created a space "new-space" with the default quota using the Graph API
And user "Alice" has uploaded a file inside space "new-space" with content "some data" to "textfile.txt"
And we save it into "FILEID"
And user "Alice" deletes file "textfile.txt" from space "new-space" using file-id "<<FILEID>>"
When the administrator restores the trash-bin item with file-id "<<FILEID>>" of space "new-space" using the CLI
Then the command should be successful
And the command output should contain "textfile.txt"
When the administrator lists the trash-bin items of space "new-space" using the CLI
Then the command should be successful
And the command output should contain "total count: 0"
Scenario: restore all trash-bin items of a personal space
Given using spaces DAV path
And user "Alice" has uploaded file with content "some data" to "textfile.txt"
And user "Alice" has uploaded file with content "some more data" to "anotherfile.txt"
And user "Alice" has deleted file "textfile.txt"
And user "Alice" has deleted file "anotherfile.txt"
When the administrator restores all the trash-bin items of the personal space of user "Alice" using the CLI
Then the command should be successful
And the command output should contain "textfile.txt"
And the command output should contain "anotherfile.txt"
And for user "Alice" the space "Personal" should contain these entries:
| textfile.txt |
| anotherfile.txt |
Scenario: restore all trash-bin items of a project space
Given using spaces DAV path
And the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API
And user "Alice" has created a space "new-space" with the default quota using the Graph API
And user "Alice" has uploaded a file inside space "new-space" with content "some data" to "textfile.txt"
And we save it into "FILEID"
And user "Alice" has uploaded a file inside space "new-space" with content "some more data" to "anotherfile.txt"
And we save it into "ANOTHER_FILEID"
And user "Alice" deletes file "textfile.txt" from space "new-space" using file-id "<<FILEID>>"
And user "Alice" deletes file "anotherfile.txt" from space "new-space" using file-id "<<ANOTHER_FILEID>>"
When the administrator restores all the trash-bin items of space "new-space" using the CLI
Then the command should be successful
And for user "Alice" the space "new-space" should contain these entries:
| textfile.txt |
| anotherfile.txt |

View File

@@ -0,0 +1,26 @@
@env-config
Feature: clean up orphaned shares via CLI command
As an admin
I want to clean up orphaned shares
So that stale share entries do not accumulate in the share manager after a shared resource has been permanently deleted
Background:
Given user "Alice" has been created with default attributes
And user "Brian" has been created with default attributes
Scenario: clean up orphaned shares after a shared folder has been permanently deleted
Given user "Alice" has created folder "/uploadFolder"
And user "Alice" has sent the following resource share invitation:
| resource | uploadFolder |
| space | Personal |
| sharee | Brian |
| shareType | user |
| permissionsRole | Editor |
And user "Alice" has deleted folder "/uploadFolder"
And user "Alice" has deleted the folder with original path "/uploadFolder" from the trashbin
When the administrator cleans up orphaned shares using the CLI
Then the command should be successful
And the command output should contain "shared resource does not exist anymore. cleaning up shares"
When user "Brian" lists the shares shared with her using the Graph API
Then the HTTP status code should be "200"

View File

@@ -234,9 +234,14 @@ func waitUntilCompleteShutdown() (bool, string) {
return true, "OpenCloud server stopped successfully"
}
func RunCommand(command string, inputs []string) (int, string) {
const defaultCommandTimeout = 5 * time.Second
func RunCommand(command string, inputs []string, timeout time.Duration) (int, string) {
logs := new(strings.Builder)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
if timeout <= 0 {
timeout = defaultCommandTimeout
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
// build the command
@@ -254,6 +259,11 @@ func RunCommand(command string, inputs []string) (int, string) {
for _, input := range inputs {
fmt.Fprintf(ptyF, "%s\n", input)
}
copyDone := make(chan struct{})
go func() {
io.Copy(logs, ptyF)
close(copyDone)
}()
var cmdOutput string
if err := c.Wait(); err != nil {
@@ -261,9 +271,7 @@ func RunCommand(command string, inputs []string) (int, string) {
cmdOutput = "Command timed out:\n"
}
}
// Copy the logs from the pty
io.Copy(logs, ptyF)
<-copyDone
cmdOutput += logs.String()
// TODO: find if there is a better way to remove stdins from the output
@@ -272,9 +280,12 @@ func RunCommand(command string, inputs []string) (int, string) {
return c.ProcessState.ExitCode(), cmdOutput
}
func RunRawCommand(command string, inputs []string) (int, string) {
func RunRawCommand(command string, inputs []string, timeout time.Duration) (int, string) {
logs := new(strings.Builder)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
if timeout <= 0 {
timeout = defaultCommandTimeout
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
fmt.Print("Running command: ", command)
@@ -290,6 +301,11 @@ func RunRawCommand(command string, inputs []string) (int, string) {
for _, input := range inputs {
fmt.Fprintf(ptyF, "%s\n", input)
}
copyDone := make(chan struct{})
go func() {
io.Copy(logs, ptyF)
close(copyDone)
}()
var cmdOutput string
if err := c.Wait(); err != nil {
@@ -297,8 +313,7 @@ func RunRawCommand(command string, inputs []string) (int, string) {
cmdOutput = "Command timed out:\n"
}
}
io.Copy(logs, ptyF)
<-copyDone
cmdOutput += logs.String()
cmdOutput = strings.TrimLeft(cmdOutput, strings.Join(inputs, "\r\n"))

View File

@@ -9,6 +9,7 @@ import (
"ocwrapper/common"
"ocwrapper/opencloud"
"os"
"time"
)
type BasicResponse struct {
@@ -203,14 +204,19 @@ func CommandHandler(res http.ResponseWriter, req *http.Request) {
raw = r
}
var timeout time.Duration
if t, ok := body["timeout"].(float64); ok {
timeout = time.Duration(t) * time.Second
}
var exitCode int
var output string
if raw {
exitCode, output = opencloud.RunRawCommand(command, stdIn)
exitCode, output = opencloud.RunRawCommand(command, stdIn, timeout)
} else {
exitCode, output = opencloud.RunCommand(command, stdIn)
exitCode, output = opencloud.RunCommand(command, stdIn, timeout)
}
sendCmdResponse(res, exitCode, output)
}