Merge pull request #2719 from nextcloud/behat-transferownership

[downstream] Behat transferownership
pull/2790/head
Lukas Reschke 8 years ago committed by GitHub
commit d7b3402643

@ -347,6 +347,15 @@ pipeline:
when:
matrix:
TESTS: integration-filesdrop-features
integration-transfer-ownership-features:
image: nextcloudci/integration-php7.0:integration-php7.0-2
commands:
- ./occ maintenance:install --admin-pass=admin
- cd build/integration
- ./run.sh features/transfer-ownership.feature
when:
matrix:
TESTS: integration-transfer-ownership-features
nodb-codecov:
image: nextcloudci/php7.0:php7.0-6
commands:
@ -392,6 +401,7 @@ matrix:
- TESTS: integration-sharees-features
- TESTS: integration-setup-features
- TESTS: integration-filesdrop-features
- TESTS: integration-transfer-ownership-features
- TESTS: jsunit
- TESTS: check-autoloader
- TESTS: app-check-code

@ -22,6 +22,9 @@ default:
baseUrl: http://localhost:8080
- ChecksumsContext:
baseUrl: http://localhost:8080
- CommandLineContext:
baseUrl: http://localhost:8080
ocPath: ../../
federation:
paths:
- %paths.base%/../federation_features
@ -73,8 +76,6 @@ default:
- admin
regular_user_password: 123456
extensions:
jarnaiz\JUnitFormatter\JUnitFormatterExtension:
filename: report.xml

@ -0,0 +1,167 @@
<?php
/**
* @author Vincent Petry <pvince81@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
require __DIR__ . '/../../vendor/autoload.php';
trait CommandLine {
/** @var int return code of last command */
private $lastCode;
/** @var string stdout of last command */
private $lastStdOut;
/** @var string stderr of last command */
private $lastStdErr;
/** @var string */
protected $ocPath = '../..';
/**
* Invokes an OCC command
*
* @param string OCC command, the part behind "occ". For example: "files:transfer-ownership"
* @return int exit code
*/
public function runOcc($args = []) {
$args = array_map(function($arg) {
return escapeshellarg($arg);
}, $args);
$args[] = '--no-ansi';
$args = implode(' ', $args);
$descriptor = [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
];
$process = proc_open('php 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);
return $this->lastCode;
}
/**
* @Given /^invoking occ with "([^"]*)"$/
*/
public function invokingTheCommand($cmd) {
$args = explode(' ', $cmd);
$this->runOcc($args);
}
/**
* Find exception texts in stderr
*/
public function findExceptions() {
$exceptions = [];
$captureNext = false;
// the exception text usually appears after an "[Exception"] row
foreach (explode("\n", $this->lastStdErr) as $line) {
if (preg_match('/\[Exception\]/', $line)) {
$captureNext = true;
continue;
}
if ($captureNext) {
$exceptions[] = trim($line);
$captureNext = false;
}
}
return $exceptions;
}
/**
* Finds all lines containing the given text
*
* @param string $input stdout or stderr output
* @param string $text text to search for
* @return array array of lines that matched
*/
public function findLines($input, $text) {
$results = [];
// the exception text usually appears after an "[Exception"] row
foreach (explode("\n", $input) as $line) {
if (strpos($line, $text) >= 0) {
$results[] = $line;
}
}
return $results;
}
/**
* @Then /^the command was successful$/
*/
public function theCommandWasSuccessful() {
$exceptions = $this->findExceptions();
if ($this->lastCode !== 0) {
$msg = 'The command was not successful, exit code was ' . $this->lastCode . '.';
if (!empty($exceptions)) {
$msg .= ' Exceptions: ' . implode(', ', $exceptions);
}
throw new \Exception($msg);
} else if (!empty($exceptions)) {
$msg = 'The command was successful but triggered exceptions: ' . implode(', ', $exceptions);
throw new \Exception($msg);
}
}
/**
* @Then /^the command failed with exit code ([0-9]+)$/
*/
public function theCommandFailedWithExitCode($exitCode) {
if ($this->lastCode !== (int)$exitCode) {
throw new \Exception('The command was expected to fail with exit code ' . $exitCode . ' but got ' . $this->lastCode);
}
}
/**
* @Then /^the command failed with exception text "([^"]*)"$/
*/
public function theCommandFailedWithException($exceptionText) {
$exceptions = $this->findExceptions();
if (empty($exceptions)) {
throw new \Exception('The command did not throw any exceptions');
}
if (!in_array($exceptionText, $exceptions)) {
throw new \Exception('The command did not throw any exception with the text "' . $exceptionText . '"');
}
}
/**
* @Then /^the command output contains the text "([^"]*)"$/
*/
public function theCommandOutputContainsTheText($text) {
$lines = $this->findLines($this->lastStdOut, $text);
if (empty($lines)) {
throw new \Exception('The command did not output the expected text on stdout "' . $exceptionText . '"');
}
}
/**
* @Then /^the command error output contains the text "([^"]*)"$/
*/
public function theCommandErrorOutputContainsTheText($text) {
$lines = $this->findLines($this->lastStdErr, $text);
if (empty($lines)) {
throw new \Exception('The command did not output the expected text on stderr "' . $exceptionText . '"');
}
}
}

@ -0,0 +1,99 @@
<?php
/**
* @author Vincent Petry <pvince81@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
require __DIR__ . '/../../vendor/autoload.php';
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
class CommandLineContext implements \Behat\Behat\Context\Context {
use CommandLine;
private $lastTransferPath;
private $featureContext;
public function __construct($ocPath, $baseUrl) {
$this->ocPath = rtrim($ocPath, '/') . '/';
$this->localBaseUrl = $baseUrl;
$this->remoteBaseUrl = $baseUrl;
}
/** @BeforeScenario */
public function gatherContexts(BeforeScenarioScope $scope) {
$environment = $scope->getEnvironment();
// this should really be "WebDavContext" ...
$this->featureContext = $environment->getContext('FeatureContext');
}
private function findLastTransferFolderForUser($sourceUser, $targetUser) {
$foundPaths = [];
$results = $this->featureContext->listFolder($targetUser, '', 1);
foreach ($results as $path => $data) {
$path = rawurldecode($path);
$parts = explode(' ', $path);
if (basename($parts[0]) !== 'transferred') {
continue;
}
if (isset($parts[2]) && $parts[2] === $sourceUser) {
// store timestamp as key
$foundPaths[] = [
'date' => strtotime(trim($parts[4], '/')),
'path' => $path,
];
}
}
if (empty($foundPaths)) {
return null;
}
usort($foundPaths, function($a, $b) {
return $a['date'] - $b['date'];
});
$davPath = rtrim($this->featureContext->getDavFilesPath($targetUser), '/');
$foundPath = end($foundPaths)['path'];
// strip dav path
return substr($foundPath, strlen($davPath) + 1);
}
/**
* @When /^transfering ownership from "([^"]+)" to "([^"]+)"/
*/
public function transferingOwnership($user1, $user2) {
if ($this->runOcc(['files:transfer-ownership', $user1, $user2]) === 0) {
$this->lastTransferPath = $this->findLastTransferFolderForUser($user1, $user2);
} else {
// failure
$this->lastTransferPath = null;
}
}
/**
* @When /^using received transfer folder of "([^"]+)" as dav path$/
*/
public function usingTransferFolderAsDavPath($user) {
$davPath = $this->featureContext->getDavFilesPath($user);
$davPath = rtrim($davPath, '/') . $this->lastTransferPath;
$this->featureContext->usingDavPath($davPath);
}
}

@ -514,6 +514,7 @@ trait WebDav {
*/
public function userCreatedAFolder($user, $destination) {
try {
$destination = '/' . ltrim($destination, '/');
$this->response = $this->makeDavRequest($user, "MKCOL", $destination, []);
} catch (\GuzzleHttp\Exception\ServerException $e) {
// 4xx and 5xx responses cause an exception

@ -0,0 +1,119 @@
Feature: transfer-ownership
Scenario: transfering ownership of a file
Given user "user0" exists
And user "user1" exists
And User "user0" uploads file "data/textfile.txt" to "/somefile.txt"
When transfering ownership from "user0" to "user1"
And the command was successful
And As an "user1"
And using received transfer folder of "user1" as dav path
Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is"
Scenario: transfering ownership of a folder
Given user "user0" exists
And user "user1" exists
And User "user0" created a folder "/test"
And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt"
When transfering ownership from "user0" to "user1"
And the command was successful
And As an "user1"
And using received transfer folder of "user1" as dav path
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
Scenario: transfering ownership of file shares
Given user "user0" exists
And user "user1" exists
And user "user2" exists
And User "user0" uploads file "data/textfile.txt" to "/somefile.txt"
And file "/somefile.txt" of user "user0" is shared with user "user2" with permissions 19
When transfering ownership from "user0" to "user1"
And the command was successful
And As an "user2"
Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is"
Scenario: transfering ownership of folder shared with third user
Given user "user0" exists
And user "user1" exists
And user "user2" exists
And User "user0" created a folder "/test"
And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt"
And folder "/test" of user "user0" is shared with user "user2" with permissions 31
When transfering ownership from "user0" to "user1"
And the command was successful
And As an "user2"
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
Scenario: transfering ownership of folder shared with transfer recipient
Given user "user0" exists
And user "user1" exists
And User "user0" created a folder "/test"
And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt"
And folder "/test" of user "user0" is shared with user "user1" with permissions 31
When transfering ownership from "user0" to "user1"
And the command was successful
And As an "user1"
Then as "user1" the folder "/test" does not exist
And using received transfer folder of "user1" as dav path
And Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
Scenario: transfering ownership of folder doubly shared with third user
Given group "group1" exists
And user "user0" exists
And user "user1" exists
And user "user2" exists
And user "user2" belongs to group "group1"
And User "user0" created a folder "/test"
And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt"
And folder "/test" of user "user0" is shared with group "group1" with permissions 31
And folder "/test" of user "user0" is shared with user "user2" with permissions 31
When transfering ownership from "user0" to "user1"
And the command was successful
And As an "user2"
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
Scenario: transfering ownership does not transfer received shares
Given user "user0" exists
And user "user1" exists
And user "user2" exists
And User "user2" created a folder "/test"
And folder "/test" of user "user2" is shared with user "user0" with permissions 31
When transfering ownership from "user0" to "user1"
And the command was successful
And As an "user1"
And using received transfer folder of "user1" as dav path
Then as "user1" the folder "/test" does not exist
@local_storage
Scenario: transfering ownership does not transfer external storage
Given user "user0" exists
And user "user1" exists
When transfering ownership from "user0" to "user1"
And the command was successful
And As an "user1"
And using received transfer folder of "user1" as dav path
Then as "user1" the folder "/local_storage" does not exist
Scenario: transfering ownership does not fail with shared trashed files
Given user "user0" exists
And user "user1" exists
And user "user2" exists
And User "user0" created a folder "/sub"
And User "user0" created a folder "/sub/test"
And folder "/sub/test" of user "user0" is shared with user "user2" with permissions 31
And User "user0" deletes folder "/sub"
When transfering ownership from "user0" to "user1"
Then the command was successful
Scenario: transfering ownership fails with invalid source user
Given user "user0" exists
When transfering ownership from "invalid_user" to "user0"
Then the command error output contains the text "Unknown source user"
And the command failed with exit code 1
Scenario: transfering ownership fails with invalid target user
Given user "user0" exists
When transfering ownership from "user0" to "invalid_user"
Then the command error output contains the text "Unknown target user"
And the command failed with exit code 1

@ -1,22 +1,15 @@
#!/usr/bin/env bash
COMPOSER=$(which composer)
OC_PATH=../../
OCC=${OC_PATH}occ
SCENARIO_TO_RUN=$1
HIDE_OC_LOGS=$2
if [ -x "$COMPOSER" ]; then
echo "Using composer executable $COMPOSER"
else
echo "Could not find composer executable" >&2
exit 1
fi
INSTALLED=$(../../occ status | grep installed: | cut -d " " -f 5)
INSTALLED=$($OCC status | grep installed: | cut -d " " -f 5)
if [ "$INSTALLED" == "true" ]; then
# Disable bruteforce protection because the integration tests do trigger them
../../occ config:system:set auth.bruteforce.protection.enabled --value false --type bool
$OCC config:system:set auth.bruteforce.protection.enabled --value false --type bool
else
if [ "$SCENARIO_TO_RUN" != "setup_features/setup.feature" ]; then
echo "Nextcloud instance needs to be installed" >&2
@ -46,33 +39,36 @@ export TEST_SERVER_URL="http://localhost:$PORT/ocs/"
export TEST_SERVER_FED_URL="http://localhost:$PORT_FED/ocs/"
if [ "$INSTALLED" == "true" ]; then
#Enable external storage app
../../occ app:enable files_external
$OCC app:enable files_external
mkdir -p work/local_storage
OUTPUT_CREATE_STORAGE=`../../occ files_external:create local_storage local null::null -c datadir=./build/integration/work/local_storage`
OUTPUT_CREATE_STORAGE=`$OCC files_external:create local_storage local null::null -c datadir=./build/integration/work/local_storage`
ID_STORAGE=`echo $OUTPUT_CREATE_STORAGE | awk {'print $5'}`
../../occ files_external:option $ID_STORAGE enable_sharing true
$OCC files_external:option $ID_STORAGE enable_sharing true
fi
vendor/bin/behat -f junit -f pretty $SCENARIO_TO_RUN
vendor/bin/behat --strict -f junit -f pretty $SCENARIO_TO_RUN
RESULT=$?
kill $PHPPID
kill $PHPPID_FED
if [ "$INSTALLED" -eq "true" ]; then
../../occ files_external:delete -y $ID_STORAGE
$OCC files_external:delete -y $ID_STORAGE
#Disable external storage app
../../occ app:disable files_external
$OCC app:disable files_external
fi
if [ -z $HIDE_OC_LOGS ]; then
tail "../../data/nextcloud.log"
tail "${OC_PATH}/data/nextcloud.log"
fi
echo "runsh: Exit code: $RESULT"
exit $RESULT

Loading…
Cancel
Save