From f4493e140ff1e3303b7d3122254f517bccd2c5f1 Mon Sep 17 00:00:00 2001 From: sakshamgurung Date: Fri, 29 Oct 2021 16:07:54 +0900 Subject: [PATCH] Adds cli test for cleaning the orphaned remote storage --- .../features/bootstrap/OccContext.php | 118 ++++++++++++------ .../cliExternalStorage/Sharing.feature | 31 +++++ 2 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 tests/acceptance/features/cliExternalStorage/Sharing.feature diff --git a/tests/acceptance/features/bootstrap/OccContext.php b/tests/acceptance/features/bootstrap/OccContext.php index 79f67e2cf6f6..13df372014f7 100644 --- a/tests/acceptance/features/bootstrap/OccContext.php +++ b/tests/acceptance/features/bootstrap/OccContext.php @@ -138,7 +138,7 @@ public function invokingTheCommand(string $cmd):void { public function importSecurityCertificateFromFileInTemporaryStorage(string $path):void { $this->invokingTheCommand("security:certificates:import " . TEMPORARY_STORAGE_DIR_ON_REMOTE_SERVER . "/$path"); if ($this->featureContext->getExitStatusCodeOfOccCommand() === 0) { - $pathComponents = \explode("/", $path); + $pathComponents = explode("/", $path); $certificate = \end($pathComponents); \array_push($this->importedCertificates, $certificate); } @@ -385,6 +385,17 @@ public function deleteSystemConfigKeyUsingTheOccCommand(string $key):void { ); } + /** + * + * @return void + * @throws Exception + */ + public function emptyOrphanedRemoteStoragesUsingOccCommand():void { + $this->invokingTheCommand( + "sharing:cleanup-remote-storages" + ); + } + /** * @param string $user * @@ -803,12 +814,12 @@ public function theCommandShouldHaveBeenSuccessful():void { "stdErr was: '" . $this->featureContext->getStdErrOfOccCommand() . "'\n"; if (!empty($exceptions)) { - $msg .= ' Exceptions: ' . \implode(', ', $exceptions); + $msg .= ' Exceptions: ' . implode(', ', $exceptions); } throw new Exception($msg); } elseif (!empty($exceptions)) { $msg = 'The command was successful but triggered exceptions: ' - . \implode(', ', $exceptions); + . implode(', ', $exceptions); throw new Exception($msg); } } @@ -956,6 +967,32 @@ public function theOccCommandJsonOutputShouldNotReturnAnyData():void { ); } + /** + * @Then :noOfOrphanedShare orphaned remote storage should have been cleared + * + * @param int $noOfOrphanedShare + * + * @return void + * @throws Exception + */ + public function theOrphanedRemoteStorageShouldBeCleared(int $noOfOrphanedShare):void { + $this->theCommandShouldHaveBeenSuccessful(); + $commandOutput = $this->featureContext->getStdOutOfOccCommand(); + // removing blank lines + $commandOutput = implode("\n", array_filter(explode("\n", $commandOutput))); + // splitting strings based on newline into an array + $outputLines = preg_split("/\r\n|\n|\r/", $commandOutput); + // calculating total no of shares deleted from remote storage: first getting total length of the array + // then minus 2 for first two lines of scan info message + // then divide by 2 because each share delete has message of two line + $totalSharesDeleted = (\count($outputLines) - 2) / 2; + Assert::assertEquals( + $noOfOrphanedShare, + $totalSharesDeleted, + "The command should delete '$noOfOrphanedShare' orphaned shares but it deletes '$totalSharesDeleted' orphaned shares." + ); + } + /** * @Given the administrator has set the default folder for received shares to :folder * @@ -988,6 +1025,7 @@ public function theAdministratorHasSetTheDefaultFolderForReceivedSharesTo(string * @param int $depth_infinity_allowed * * @return void + * @throws Exception */ public function theAdministratorHasSetDepthInfinityAllowedTo($depth_infinity_allowed) { $this->addSystemConfigKeyUsingTheOccCommand( @@ -1104,8 +1142,8 @@ public function theAdministratorSetsLogRotateFileSizeUsingTheOccCommand(string $ public function theCommandOutputShouldBe(PyStringNode $content):void { $commandOutput = $this->featureContext->getStdOutOfOccCommand(); // removing blank lines - $commandOutput = \implode("\n", \array_filter(\explode("\n", $commandOutput))); - $content = \implode("\n", \array_filter(\explode("\n", $content->getRaw()))); + $commandOutput = implode("\n", array_filter(explode("\n", $commandOutput))); + $content = implode("\n", array_filter(explode("\n", $content->getRaw()))); Assert::assertEquals( $content, $commandOutput, @@ -1709,7 +1747,7 @@ public function theFollowingLocalStoragesShouldExist(TableNode $mountPoints):voi $expectedStorageEntry['localStorage'], $createdLocalStorage, "'" - . \implode(', ', $createdLocalStorage) + . implode(', ', $createdLocalStorage) . "' does not contain '${expectedStorageEntry['localStorage']}' " . __METHOD__ ); @@ -1757,7 +1795,7 @@ public function theFollowingBackendTypesShouldBeListed(TableNode $table):void { $expectedBackendTypeEntry, __METHOD__ . " The provided expected backend type entry '" - . \implode(', ', $expectedBackendTypeEntry) + . implode(', ', $expectedBackendTypeEntry) . "' do not have key 'backend-type'" ); } @@ -1769,7 +1807,7 @@ public function theFollowingBackendTypesShouldBeListed(TableNode $table):void { $keys, __METHOD__ . " ${backendTypesEntry['backend-type']} is not contained in '" - . \implode(', ', $keys) + . implode(', ', $keys) . "' but was expected to be." ); } @@ -1791,7 +1829,7 @@ public function theFollowingBackendsShouldBeListed(TableNode $table):void { $expectedBackendEntry, __METHOD__ . " The provided expected backend entry '" - . \implode(', ', $expectedBackendEntry) + . implode(', ', $expectedBackendEntry) . "' do not have key 'backends'" ); } @@ -1803,7 +1841,7 @@ public function theFollowingBackendsShouldBeListed(TableNode $table):void { $keys, __METHOD__ . " ${backendsEntry['backends']} is not contained in '" - . \implode(', ', $keys) + . implode(', ', $keys) . "' but was expected to be." ); } @@ -1825,7 +1863,7 @@ public function theFollowingBackendKeysOfTypeShouldBeListed(TableNode $table):vo $expectedBackendKeyEntry, __METHOD__ . " The provided expected backend key entry '" - . \implode(', ', $expectedBackendKeyEntry) + . implode(', ', $expectedBackendKeyEntry) . "' do not have key 'backend-keys'" ); } @@ -1837,7 +1875,7 @@ public function theFollowingBackendKeysOfTypeShouldBeListed(TableNode $table):vo $keys, __METHOD__ . " ${backendKeysEntry['backend-keys']} is not contained in '" - . \implode(', ', $keys) + . implode(', ', $keys) . "' but was expected to be." ); } @@ -1925,7 +1963,7 @@ public function theFollowingLocalStorageShouldBeListed(TableNode $table):void { if ($listedStorageEntry->applicable_users === '') { $listedApplicableUsers = []; } else { - $listedApplicableUsers = \explode(', ', $listedStorageEntry->applicable_users); + $listedApplicableUsers = explode(', ', $listedStorageEntry->applicable_users); } } else { $listedApplicableUsers = $listedStorageEntry->applicable_users; @@ -1937,7 +1975,7 @@ public function theFollowingLocalStorageShouldBeListed(TableNode $table):void { "ApplicableUsers was expected to be an empty array but was not empty" ); } else { - $expectedApplicableUsers = \explode(', ', $expectedStorageEntry['ApplicableUsers']); + $expectedApplicableUsers = explode(', ', $expectedStorageEntry['ApplicableUsers']); foreach ($expectedApplicableUsers as $expectedApplicableUserEntry) { $expectedApplicableUserEntry = $this->featureContext->getActualUsername($expectedApplicableUserEntry); Assert::assertContains( @@ -1945,7 +1983,7 @@ public function theFollowingLocalStorageShouldBeListed(TableNode $table):void { $listedApplicableUsers, __METHOD__ . " '$expectedApplicableUserEntry' is not listed in '" - . \implode(', ', $listedApplicableUsers) + . implode(', ', $listedApplicableUsers) . "'" ); } @@ -1956,7 +1994,7 @@ public function theFollowingLocalStorageShouldBeListed(TableNode $table):void { if ($listedStorageEntry->applicable_groups === '') { $listedApplicableGroups = []; } else { - $listedApplicableGroups = \explode(', ', $listedStorageEntry->applicable_groups); + $listedApplicableGroups = explode(', ', $listedStorageEntry->applicable_groups); } } else { $listedApplicableGroups = $listedStorageEntry->applicable_groups; @@ -1969,14 +2007,14 @@ public function theFollowingLocalStorageShouldBeListed(TableNode $table):void { ); Assert::assertEquals([], $listedApplicableGroups); } else { - $expectedApplicableGroups = \explode(', ', $expectedStorageEntry['ApplicableGroups']); + $expectedApplicableGroups = explode(', ', $expectedStorageEntry['ApplicableGroups']); foreach ($expectedApplicableGroups as $expectedApplicableGroupEntry) { Assert::assertContains( $expectedApplicableGroupEntry, $listedApplicableGroups, __METHOD__ . " '$expectedApplicableGroupEntry' is not listed in '" - . \implode(', ', $listedApplicableGroups) + . implode(', ', $listedApplicableGroups) . "'" ); } @@ -2034,7 +2072,7 @@ public function theFollowingShouldBeIncludedInTheConfigurationOfLocalStorage(str $expectedConfigurationEntry, __METHOD__ . " The provided expected configuration entry '" - . \implode(', ', $expectedConfigurationEntry) + . implode(', ', $expectedConfigurationEntry) . "' do not have key 'configuration'" ); } @@ -2044,7 +2082,7 @@ public function theFollowingShouldBeIncludedInTheConfigurationOfLocalStorage(str if ($listedStorageEntry->mount_point === $localStorage) { $isStorageEntryListed = true; $configurations = $listedStorageEntry->configuration; - $configurationsSplitted = \explode(', ', $configurations); + $configurationsSplitted = explode(', ', $configurations); foreach ($expectedConfigurations as $expectedConfigArray) { foreach ($expectedConfigArray as $expectedConfigEntry) { Assert::assertContains( @@ -2052,7 +2090,7 @@ public function theFollowingShouldBeIncludedInTheConfigurationOfLocalStorage(str $configurationsSplitted, __METHOD__ . " $expectedConfigEntry is not contained in '" - . \implode(', ', $configurationsSplitted) + . implode(', ', $configurationsSplitted) . "' but was expected to be." ); } @@ -2103,7 +2141,7 @@ public function theFollowingShouldBeIncludedInTheOptionsOfLocalStorage(string $l $expectedOptionEntry, __METHOD__ . " The provided expected option '" - . \implode(', ', $expectedOptionEntry) + . implode(', ', $expectedOptionEntry) . "' do not have key 'option'" ); } @@ -2113,7 +2151,7 @@ public function theFollowingShouldBeIncludedInTheOptionsOfLocalStorage(string $l if ($listedStorageEntry->mount_point === $localStorage) { $isStorageEntryListed = true; $options = $listedStorageEntry->options; - $optionsSplitted = \explode(', ', $options); + $optionsSplitted = explode(', ', $options); foreach ($expectedOptions as $expectedOptionArray) { foreach ($expectedOptionArray as $expectedOptionEntry) { Assert::assertContains( @@ -2121,7 +2159,7 @@ public function theFollowingShouldBeIncludedInTheOptionsOfLocalStorage(string $l $optionsSplitted, __METHOD__ . " $expectedOptionEntry is not contained in '" - . \implode(', ', $optionsSplitted) + . implode(', ', $optionsSplitted) . "' , but was expected to be." ); } @@ -2149,7 +2187,7 @@ public function theFollowingShouldNotBeIncludedInTheOptionsOfLocalStorage(string $expectedOptionEntry, __METHOD__ . " The provided expected option '" - . \implode(', ', $expectedOptionEntry) + . implode(', ', $expectedOptionEntry) . "' do not have key 'options'" ); } @@ -2159,7 +2197,7 @@ public function theFollowingShouldNotBeIncludedInTheOptionsOfLocalStorage(string if ($listedStorageEntry->mount_point === $localStorage) { $isStorageEntryListed = true; $options = $listedStorageEntry->options; - $optionsSplitted = \explode(', ', $options); + $optionsSplitted = explode(', ', $options); foreach ($expectedOptions as $expectedOptionArray) { foreach ($expectedOptionArray as $expectedOptionEntry) { Assert::assertNotContains( @@ -2167,7 +2205,7 @@ public function theFollowingShouldNotBeIncludedInTheOptionsOfLocalStorage(string $optionsSplitted, __METHOD__ . " $expectedOptionEntry is contained in '" - . \implode(', ', $optionsSplitted) + . implode(', ', $optionsSplitted) . "' , but was not expected to be." ); } @@ -2208,10 +2246,10 @@ public function administratorHasDeletedLocalStorageFolderUsingTheOccCommand(stri * @param string $folder * @param bool $mustExist * - * @return integer + * @return integer|bool * @throws Exception */ - public function deleteLocalStorageFolderUsingTheOccCommand(string $folder, bool $mustExist = true):int { + public function deleteLocalStorageFolderUsingTheOccCommand(string $folder, bool $mustExist = true) { $createdLocalStorage = []; $this->listLocalStorageMount(); $commandOutput = \json_decode($this->featureContext->getStdOutOfOccCommand()); @@ -2302,7 +2340,7 @@ public function theFollowingInformationShouldBeListed(TableNode $info):void { $expectedInfo = $info->getColumnsHash(); $commandOutput = $this->featureContext->getStdOutOfOccCommand(); $commandOutputSplitted = \preg_split("/[-]/", $commandOutput); - $filteredArray = \array_filter(\array_map("trim", $commandOutputSplitted)); + $filteredArray = array_filter(\array_map("trim", $commandOutputSplitted)); foreach ($filteredArray as $entry) { $keyValue = \preg_split("/[:]/", $entry); if (isset($keyValue[1])) { @@ -2316,7 +2354,7 @@ public function theFollowingInformationShouldBeListed(TableNode $info):void { $element, \array_map('trim', $ResultArray), __METHOD__ - . " '" . \implode(', ', $element) + . " '" . implode(', ', $element) . "' was expected to be listed, but is not listed in the mount configuration information" ); } @@ -2532,6 +2570,16 @@ public function theAdministratorDeletesAllTheVersionsForUser(string $user):void $this->deleteAllVersionsForUserUsingOccCommand($user); } + /** + * @When the administrator cleanups all the orphaned remote storages of shares + * + * @return void + * @throws Exception + */ + public function theAdministratorCleanupsAllTheOrphanedRemoteStoragesOfShares():void { + $this->emptyOrphanedRemoteStoragesUsingOccCommand(); + } + /** * @When the administrator deletes all the versions for the following users: * @@ -2793,10 +2841,10 @@ public function theAdministratorHasClearedTheVersionsForAllUsers():void { * * @param string $job * - * @return string + * @return string|bool * @throws Exception */ - public function getLastJobIdForJob(string $job):string { + public function getLastJobIdForJob(string $job) { $this->getAllJobsInBackgroundQueueUsingOccCommand(); $commandOutput = $this->featureContext->getStdOutOfOccCommand(); $lines = SetupHelper::findLines( @@ -2914,9 +2962,9 @@ public function enableExternalStorageUsingOccAsAdmin():void { * @throws Exception */ public function theAdministratorHasAddedGroupToTheExcludeGroupFromSharingList(string $groups):void { - $groups = \explode(',', \trim($groups)); + $groups = explode(',', \trim($groups)); $groups = \array_map('trim', $groups); //removing whitespaces around group names - $groups = '"' . \implode('","', $groups) . '"'; + $groups = '"' . implode('","', $groups) . '"'; SetupHelper::runOcc( [ 'config:app:set', diff --git a/tests/acceptance/features/cliExternalStorage/Sharing.feature b/tests/acceptance/features/cliExternalStorage/Sharing.feature new file mode 100644 index 000000000000..d07882075f20 --- /dev/null +++ b/tests/acceptance/features/cliExternalStorage/Sharing.feature @@ -0,0 +1,31 @@ +@cli @api @federation-app-required @files_sharing-app-required +Feature: + As a admin + I want to cleanup orphaned remote storages + So that users will not get undesirable failure + + Background: + Given using server "REMOTE" + And user "Alice" has been created with default attributes and without skeleton files + And using server "LOCAL" + And user "Brian" has been created with default attributes and without skeleton files + + Scenario Outline: Clean up the orphaned remote storage after deleting the original shares + Given using OCS API version "" + And using server "REMOTE" + And user "Alice" has uploaded file "filesForUpload/textfile.txt" to "textfile0.txt" + And user "Alice" has uploaded file "filesForUpload/textfile.txt" to "textfile1.txt" + And user "Alice" from server "REMOTE" has shared "/textfile0.txt" with user "Brian" from server "LOCAL" + And user "Brian" from server "LOCAL" has accepted the last pending share + And user "Alice" has deleted the last share + And user "Alice" from server "REMOTE" has shared "/textfile1.txt" with user "Brian" from server "LOCAL" + And user "Brian" from server "LOCAL" has accepted the last pending share + And user "Alice" has deleted the last share + And using server "LOCAL" + When the administrator cleanups all the orphaned remote storages of shares + Then 2 orphaned remote storage should have been cleared + + Examples: + | ocs-api-version | + | 1 | + | 2 | \ No newline at end of file