diff --git a/.drone.yml b/.drone.yml index 79cd295210eba..7ad8e60014b38 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1025,6 +1025,31 @@ trigger: - pull_request - push +--- +kind: pipeline +name: integration-files + +steps: +- name: submodules + image: ghcr.io/nextcloud/continuous-integration-alpine-git:latest + commands: + - git submodule update --init +- name: integration-files + image: ghcr.io/nextcloud/continuous-integration-integration-php7.4:latest + commands: + - bash tests/drone-run-integration-tests.sh || exit 0 + - ./occ maintenance:install --admin-pass=admin --data-dir=/dev/shm/nc_int + - cd build/integration + - ./run.sh features/files.feature + +trigger: + branch: + - master + - stable* + event: + - pull_request + - push + --- kind: pipeline name: integration-provisioning-v2 diff --git a/build/integration/config/behat.yml b/build/integration/config/behat.yml index 0e577f5925e69..aa992661f21e4 100644 --- a/build/integration/config/behat.yml +++ b/build/integration/config/behat.yml @@ -116,6 +116,9 @@ default: - admin - admin regular_user_password: 123456 + - CommandLineContext: + baseUrl: http://localhost:8080 + ocPath: ../../ - RemoteContext: remote: http://localhost:8080 extensions: diff --git a/build/integration/features/bootstrap/CommandLine.php b/build/integration/features/bootstrap/CommandLine.php index cba254551e0c4..017176f1ca4f7 100644 --- a/build/integration/features/bootstrap/CommandLine.php +++ b/build/integration/features/bootstrap/CommandLine.php @@ -42,21 +42,27 @@ trait CommandLine { * Invokes an OCC command * * @param []string $args OCC command, the part behind "occ". For example: "files:transfer-ownership" + * @param []string $phpArgs optional PHP command arguments. For example: "--define apc.enable_cli=1" * @return int exit code */ - public function runOcc($args = []) { + public function runOcc($args = [], $phpArgs = []) { $args = array_map(function ($arg) { return escapeshellarg($arg); }, $args); $args[] = '--no-ansi'; $args = implode(' ', $args); + $phpArgs = array_map(function ($phpArg) { + return escapeshellarg($phpArg); + }, $phpArgs); + $phpArgs = implode(' ', $phpArgs); + $descriptor = [ 0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ]; - $process = proc_open('php console.php ' . $args, $descriptor, $pipes, $this->ocPath); + $process = proc_open('php ' . $phpArgs . ' console.php ' . $args, $descriptor, $pipes, $this->ocPath); $this->lastStdOut = stream_get_contents($pipes[1]); $this->lastStdErr = stream_get_contents($pipes[2]); $this->lastCode = proc_close($process); diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index a3a600d66256c..2d1dd75191a4f 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -34,6 +34,7 @@ */ class FeatureContext implements Context, SnippetAcceptingContext { use ContactsMenu; + use Files; use Search; use WebDav; use Trashbin; diff --git a/build/integration/features/bootstrap/Files.php b/build/integration/features/bootstrap/Files.php new file mode 100644 index 0000000000000..036a974a9ffd2 --- /dev/null +++ b/build/integration/features/bootstrap/Files.php @@ -0,0 +1,84 @@ + + * + * @author Daniel Calviño Sánchez + * + * @license GNU AGPL version 3 or any later version + * + * This program 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 (at your option) 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 . + * + */ +use Behat\Behat\Hook\Scope\AfterScenarioScope; +use PHPUnit\Framework\Assert; + +require __DIR__ . '/../../vendor/autoload.php'; + +trait Files { + + // BasicStructure trait is expected to be used in the class that uses this + // trait. + // CommandLineContext is expected to be loaded in the Behat suite where this + // trait is used. + + /** + * @AfterScenario + */ + public function disableMemcacheLocal(AfterScenarioScope $scope) { + $environment = $scope->getEnvironment(); + $commandLineContext = $environment->getContext('CommandLineContext'); + + // If APCu was set APC needs to be enabled for the CLI when running OCC; + // otherwise OC\Memcache\APCu is not available and OCC command fails, + // even if it is just trying to disable the memcache. + $commandLineContext->runOcc(['config:system:delete', 'memcache.local'], ['--define', 'apc.enable_cli=1']); + } + + /** + * @When logged in user gets storage stats of folder :folder + * + * @param string $folder + */ + public function loggedInUserGetsStorageStatsOfFolder(string $folder) { + $this->loggedInUserGetsStorageStatsOfFolderWith($folder, '200'); + } + + /** + * @When logged in user gets storage stats of folder :folder with :statusCode + * + * @param string $folder + */ + public function loggedInUserGetsStorageStatsOfFolderWith(string $folder, string $statusCode) { + $this->sendingAToWithRequesttoken('GET', '/index.php/apps/files/ajax/getstoragestats?dir=' . $folder); + $this->theHTTPStatusCodeShouldBe($statusCode); + } + + /** + * @Then the storage stats match with + * + * @param Behat\Gherkin\Node\TableNode $body + */ + public function theStorageStatsMatchWith(Behat\Gherkin\Node\TableNode $body) { + $storageStats = json_decode($this->response->getBody()->getContents(), $asAssociativeArray = true); + $storageStats = $storageStats['data']; + + foreach ($body->getRowsHash() as $expectedField => $expectedValue) { + if (!array_key_exists($expectedField, $storageStats)) { + Assert::fail("$expectedField was not found in response"); + } + + Assert::assertEquals($expectedValue, $storageStats[$expectedField], "Field '$expectedField' does not match ({$storageStats[$expectedField]})"); + } + } +} diff --git a/build/integration/features/files.feature b/build/integration/features/files.feature new file mode 100644 index 0000000000000..f2a820e16c566 --- /dev/null +++ b/build/integration/features/files.feature @@ -0,0 +1,104 @@ +Feature: files + + # Counterpart scenarios for getting the folder size in webdav-related.feature + + Scenario: Retrieving storage stats after a file was uploaded + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 108 bytes to "/test.txt" + When Logging in using web as "user0" + And logged in user gets storage stats of folder "/" + Then the storage stats match with + | used | 447 | + + Scenario: Retrieving storage stats after a file was uploaded to a folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 108 bytes to "/FOLDER/test.txt" + When Logging in using web as "user0" + And logged in user gets storage stats of folder "/" + Then the storage stats match with + | used | 447 | + + Scenario: Retrieving storage stats for folder after a file was uploaded to that folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 108 bytes to "/FOLDER/test.txt" + When Logging in using web as "user0" + And logged in user gets storage stats of folder "/FOLDER/" + Then the storage stats match with + | used | 108 | + + Scenario: Retrieving storage stats after a file was deleted from a folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 23 bytes to "/FOLDER/test1.txt" + And user "user0" adds a file of 42 bytes to "/FOLDER/test2.txt" + And user "user0" adds a file of 108 bytes to "/FOLDER/test3.txt" + And User "user0" deletes file "/FOLDER/test2.txt" + When Logging in using web as "user0" + And logged in user gets storage stats of folder "/" + Then the storage stats match with + | used | 470 | + + Scenario: Retrieving storage stats for folder after a file was deleted from that folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 23 bytes to "/FOLDER/test1.txt" + And user "user0" adds a file of 42 bytes to "/FOLDER/test2.txt" + And user "user0" adds a file of 108 bytes to "/FOLDER/test3.txt" + And User "user0" deletes file "/FOLDER/test2.txt" + When Logging in using web as "user0" + And logged in user gets storage stats of folder "/FOLDER/" + Then the storage stats match with + | used | 131 | + + Scenario: Retrieving storage stats after the last file was deleted from a folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 108 bytes to "/FOLDER/test.txt" + And Logging in using web as "user0" + # Get the size after uploading the file to ensure that the size after the + # deletion is not just a size cached before the upload. + And logged in user gets storage stats of folder "/" + And the storage stats match with + | used | 447 | + And User "user0" deletes file "/FOLDER/test.txt" + When logged in user gets storage stats of folder "/" + Then the storage stats match with + | used | 339 | + + Scenario: Retrieving storage stats for folder after the last file was deleted from that folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 108 bytes to "/FOLDER/test.txt" + And Logging in using web as "user0" + # Get the size after uploading the file to ensure that the size after the + # deletion is not just a size cached before the upload. + And logged in user gets storage stats of folder "/" + And the storage stats match with + | used | 447 | + And User "user0" deletes file "/FOLDER/test.txt" + When logged in user gets storage stats of folder "/FOLDER/" + Then the storage stats match with + | used | 0 | + + # End of counterpart scenarios + + Scenario: Retrieving storage stats after a file was uploaded when using APCu + Given using old dav path + And invoking occ with "config:system:set memcache.local --value \OC\Memcache\APCu --type string" + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 108 bytes to "/test.txt" + When Logging in using web as "user0" + And logged in user gets storage stats of folder "/" + Then the storage stats match with + | used | 447 | diff --git a/build/integration/features/webdav-related.feature b/build/integration/features/webdav-related.feature index efaea1a43c4ba..7a6340596393d 100644 --- a/build/integration/features/webdav-related.feature +++ b/build/integration/features/webdav-related.feature @@ -223,6 +223,91 @@ Feature: webdav-related |{DAV:}quota-available-bytes| Then the single response should contain a property "{DAV:}quota-available-bytes" with value "685" + # Counterpart scenarios for getting the storage stats in files.feature + + Scenario: Retrieving root folder size after a file was uploaded + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 108 bytes to "/test.txt" + When as "user0" gets properties of folder "/" with + |{http://owncloud.org/ns}size| + Then the single response should contain a property "{http://owncloud.org/ns}size" with value "447" + + Scenario: Retrieving root folder size after a file was uploaded to a folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 108 bytes to "/FOLDER/test.txt" + When as "user0" gets properties of folder "/" with + |{http://owncloud.org/ns}size| + Then the single response should contain a property "{http://owncloud.org/ns}size" with value "447" + + Scenario: Retrieving folder size after a file was uploaded to that folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 108 bytes to "/FOLDER/test.txt" + When as "user0" gets properties of folder "/FOLDER/" with + |{http://owncloud.org/ns}size| + Then the single response should contain a property "{http://owncloud.org/ns}size" with value "108" + + Scenario: Retrieving root folder size after a file was deleted from a folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 23 bytes to "/FOLDER/test1.txt" + And user "user0" adds a file of 42 bytes to "/FOLDER/test2.txt" + And user "user0" adds a file of 108 bytes to "/FOLDER/test3.txt" + And User "user0" deletes file "/FOLDER/test2.txt" + When as "user0" gets properties of folder "/" with + |{http://owncloud.org/ns}size| + Then the single response should contain a property "{http://owncloud.org/ns}size" with value "470" + + Scenario: Retrieving folder size after a file was deleted from that folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 23 bytes to "/FOLDER/test1.txt" + And user "user0" adds a file of 42 bytes to "/FOLDER/test2.txt" + And user "user0" adds a file of 108 bytes to "/FOLDER/test3.txt" + And User "user0" deletes file "/FOLDER/test2.txt" + When as "user0" gets properties of folder "/FOLDER/" with + |{http://owncloud.org/ns}size| + Then the single response should contain a property "{http://owncloud.org/ns}size" with value "131" + + Scenario: Retrieving root folder size after the last file was deleted from a folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 108 bytes to "/FOLDER/test.txt" + # Get the size after uploading the file to ensure that the size after the + # deletion is not just a size cached before the upload. + And as "user0" gets properties of folder "/" with + |{http://owncloud.org/ns}size| + And the single response should contain a property "{http://owncloud.org/ns}size" with value "447" + And User "user0" deletes file "/FOLDER/test.txt" + When as "user0" gets properties of folder "/" with + |{http://owncloud.org/ns}size| + Then the single response should contain a property "{http://owncloud.org/ns}size" with value "339" + + Scenario: Retrieving folder size after the last file was deleted from that folder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" adds a file of 108 bytes to "/FOLDER/test.txt" + # Get the size after uploading the file to ensure that the size after the + # deletion is not just a size cached before the upload. + And as "user0" gets properties of folder "/FOLDER/" with + |{http://owncloud.org/ns}size| + And the single response should contain a property "{http://owncloud.org/ns}size" with value "108" + And User "user0" deletes file "/FOLDER/test.txt" + When as "user0" gets properties of folder "/FOLDER/" with + |{http://owncloud.org/ns}size| + Then the single response should contain a property "{http://owncloud.org/ns}size" with value "0" + + # End of counterpart scenarios + Scenario: download a public shared file with range Given user "user0" exists And As an "user0"