Merge pull request #7628 from owncloud/backport/createLockFileTest

[test-only] [full-ci] Backport lock tests
This commit is contained in:
Phil Davis
2023-11-01 12:40:07 +05:45
committed by GitHub
5 changed files with 348 additions and 66 deletions

View File

@@ -46,6 +46,7 @@ default:
- SpacesTUSContext:
- GraphContext:
- OcisConfigContext:
- WebDavLockingContext:
apiSpacesShares:
paths:

View File

@@ -143,5 +143,16 @@ The expected failures in this file are from features in the owncloud/ocis repo.
- [apiGraph/addUserToGroup.feature:420](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L420)
### [500 error if viewer tries to lock file](https://github.com/owncloud/ocis/issues/7600)
- [apiSpaces/lockFiles.feature:144](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpaces/lockFiles.feature#L144)
- [apiSpaces/lockFiles.feature:207](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpaces/lockFiles.feature#L207)
### [Shared file locking is not possible using different path](https://github.com/owncloud/ocis/issues/7599)
- [apiSpaces/lockFiles.feature:179](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpaces/lockFiles.feature#L179)
- [apiSpaces/lockFiles.feature:180](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpaces/lockFiles.feature#L180)
- [apiSpaces/lockFiles.feature:181](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpaces/lockFiles.feature#L181)
Note: always have an empty line at the end of this file.
The bash script that processes this file requires that the last line has a newline on the end.

View File

@@ -0,0 +1,216 @@
Feature: lock files
As a user
I want to lock files
Background:
Given these users have been created with default attributes and without skeleton files:
| username |
| Alice |
| Brian |
Scenario Outline: lock a file
Given using <dav-path-version> DAV path
And user "Alice" has uploaded a file inside space "Alice Hansen" with content "some content" to "textfile.txt"
When user "Alice" locks file "textfile.txt" using the WebDAV API setting the following properties
| lockscope | exclusive |
Then the HTTP status code should be "200"
When user "Alice" sends PROPFIND request from the space "Alice Hansen" to the resource "textfile.txt" using the WebDAV API
Then the HTTP status code should be "207"
And the "PROPFIND" response to user "Alice" should contain a space "Alice Hansen" with these key and value pairs:
| key | value |
| d:lockdiscovery/d:activelock/d:lockscope/d:exclusive | |
| d:lockdiscovery/d:activelock/d:depth | Infinity |
| d:lockdiscovery/d:activelock/d:timeout | Infinity |
# | d:lockdiscovery/d:activelock/oc:ownername | Alice Hansen | no "oc:ownername" property in stable-4.0
Examples:
| dav-path-version |
| old |
| new |
| spaces |
Scenario Outline: lock a file with a timeout
Given using <dav-path-version> DAV path
And user "Alice" has uploaded a file inside space "Alice Hansen" with content "some content" to "textfile.txt"
When user "Alice" locks file "textfile.txt" using the WebDAV API setting the following properties
| lockscope | exclusive |
| timeout | Second-5000 |
Then the HTTP status code should be "200"
When user "Alice" sends PROPFIND request from the space "Alice Hansen" to the resource "textfile.txt" using the WebDAV API
Then the HTTP status code should be "207"
And the "PROPFIND" response to user "Alice" should contain a space "Alice Hansen" with these key and value pairs:
| key | value |
| d:lockdiscovery/d:activelock/d:lockscope/d:exclusive | |
| d:lockdiscovery/d:activelock/d:depth | Infinity |
| d:lockdiscovery/d:activelock/d:timeout | Second-5000 |
# | d:lockdiscovery/d:activelock/oc:ownername | Alice Hansen | no "oc:ownername" property in stable-4.0
Examples:
| dav-path-version |
| old |
| new |
| spaces |
Scenario Outline: lock a file using file-id
Given user "Alice" has uploaded a file inside space "Alice Hansen" with content "some content" to "textfile.txt"
And we save it into "FILEID"
When user "Alice" locks file using file-id path "<dav-path>" using the WebDAV API setting the following properties
| lockscope | exclusive |
| timeout | Second-3600 |
Then the HTTP status code should be "200"
When user "Alice" sends PROPFIND request from the space "Alice Hansen" to the resource "textfile.txt" using the WebDAV API
Then the HTTP status code should be "207"
And the "PROPFIND" response to user "Alice" should contain a space "Alice Hansen" with these key and value pairs:
| key | value |
| d:lockdiscovery/d:activelock/d:lockscope/d:exclusive | |
| d:lockdiscovery/d:activelock/d:depth | Infinity |
| d:lockdiscovery/d:activelock/d:timeout | Second-3600 |
# | d:lockdiscovery/d:activelock/oc:ownername | Alice Hansen | no "oc:ownername" property in stable-4.0
Examples:
| dav-path |
| /remote.php/dav/spaces/<<FILEID>> |
| /dav/spaces/<<FILEID>> |
Scenario Outline: user cannot lock file twice
Given using <dav-path-version> DAV path
And user "Alice" has uploaded a file inside space "Alice Hansen" with content "some content" to "textfile.txt"
And user "Alice" has locked file "textfile.txt" setting the following properties
| lockscope | exclusive |
When user "Alice" tries to lock file "textfile.txt" using the WebDAV API setting the following properties
| lockscope | exclusive |
Then the HTTP status code should be "423"
Examples:
| dav-path-version |
| old |
| new |
| spaces |
Scenario Outline: lock a file in the project space
Given the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API
And using spaces DAV path
And user "Alice" has created a space "Project" with the default quota using the GraphApi
And user "Alice" has uploaded a file inside space "Project" with content "some content" to "textfile.txt"
And user "Alice" has shared a space "Project" with settings:
| shareWith | Brian |
| role | <role> |
When user "Brian" locks file "textfile.txt" inside the space "Project" using the WebDAV API setting the following properties
| lockscope | exclusive |
| timeout | Second-3600 |
Then the HTTP status code should be "200"
When user "Brian" sends PROPFIND request from the space "Project" to the resource "textfile.txt" using the WebDAV API
Then the HTTP status code should be "207"
And the "PROPFIND" response to user "Brian" should contain a space "Project" with these key and value pairs:
| key | value |
| d:lockdiscovery/d:activelock/d:lockscope/d:exclusive | |
| d:lockdiscovery/d:activelock/d:depth | Infinity |
| d:lockdiscovery/d:activelock/d:timeout | Second-3600 |
# | d:lockdiscovery/d:activelock/oc:ownername | Brian Murphy | no "oc:ownername" property in stable-4.0
Examples:
| role |
| manager |
| editor |
Scenario Outline: lock a file in the project space using file-id
Given the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API
And using spaces DAV path
And user "Alice" has created a space "Project" with the default quota using the GraphApi
And user "Alice" has uploaded a file inside space "Project" with content "some content" to "textfile.txt"
And we save it into "FILEID"
And user "Alice" has shared a space "Project" with settings:
| shareWith | Brian |
| role | <role> |
When user "Brian" locks file using file-id path "<dav-path>" using the WebDAV API setting the following properties
| lockscope | exclusive |
| timeout | Second-3600 |
Then the HTTP status code should be "200"
When user "Brian" sends PROPFIND request from the space "Project" to the resource "textfile.txt" using the WebDAV API
Then the HTTP status code should be "207"
And the "PROPFIND" response to user "Brian" should contain a space "Project" with these key and value pairs:
| key | value |
| d:lockdiscovery/d:activelock/d:lockscope/d:exclusive | |
| d:lockdiscovery/d:activelock/d:depth | Infinity |
| d:lockdiscovery/d:activelock/d:timeout | Second-3600 |
# | d:lockdiscovery/d:activelock/oc:ownername | Brian Murphy | no "oc:ownername" property in stable-4.0
Examples:
| role | dav-path |
| manager | /remote.php/dav/spaces/<<FILEID>> |
| editor | /dav/spaces/<<FILEID>> |
Scenario: viewer cannot lock a file in the project space
Given the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API
And using spaces DAV path
And user "Alice" has created a space "Project" with the default quota using the GraphApi
And user "Alice" has uploaded a file inside space "Project" with content "some content" to "textfile.txt"
And we save it into "FILEID"
And user "Alice" has shared a space "Project" with settings:
| shareWith | Brian |
| role | viewer |
When user "Brian" locks file "textfile.txt" inside the space "Project" using the WebDAV API setting the following properties
| lockscope | exclusive |
Then the HTTP status code should be "403"
When user "Brian" locks file using file-id path "/dav/spaces/<<FILEID>>" using the WebDAV API setting the following properties
| lockscope | exclusive |
Then the HTTP status code should be "403"
Scenario Outline: lock a file in the shares
Given using <dav-path-version> DAV path
And user "Alice" has uploaded a file inside space "Alice Hansen" with content "some content" to "textfile.txt"
And user "Alice" has created a share inside of space "Alice Hansen" with settings:
| path | textfile.txt |
| shareWith | Brian |
| role | editor |
When user "Brian" locks file "/Shares/textfile.txt" using the WebDAV API setting the following properties
| lockscope | exclusive |
Then the HTTP status code should be "200"
When user "Alice" sends PROPFIND request from the space "Alice Hansen" to the resource "textfile.txt" using the WebDAV API
Then the HTTP status code should be "207"
And the "PROPFIND" response to user "Alice" should contain a space "Alice Hansen" with these key and value pairs:
| key | value |
| d:lockdiscovery/d:activelock/d:lockscope/d:exclusive | |
# | d:lockdiscovery/d:activelock/oc:ownername | Brian Murphy | no "oc:ownername" property in stable-4.0
Examples:
| dav-path-version |
| old |
| new |
| spaces |
Scenario Outline: lock a file in the shares using file-id
Given user "Alice" has uploaded a file inside space "Alice Hansen" with content "some content" to "textfile.txt"
And we save it into "FILEID"
And user "Alice" has created a share inside of space "Alice Hansen" with settings:
| path | textfile.txt |
| shareWith | Brian |
| role | editor |
When user "Brian" locks file using file-id path "<dav-path>" using the WebDAV API setting the following properties
| lockscope | exclusive |
| timeout | Second-3600 |
Then the HTTP status code should be "200"
When user "Alice" sends PROPFIND request from the space "Alice Hansen" to the resource "textfile.txt" using the WebDAV API
Then the HTTP status code should be "207"
And the "PROPFIND" response to user "Alice" should contain a space "Alice Hansen" with these key and value pairs:
| key | value |
| d:lockdiscovery/d:activelock/d:lockscope/d:exclusive | |
# | d:lockdiscovery/d:activelock/oc:ownername | Brian Murphy | no "oc:ownername" property in stable-4.0
Examples:
| dav-path |
| /remote.php/dav/spaces/<<FILEID>> |
| /dav/spaces/<<FILEID>> |
Scenario: viewer cannot lock a file in the shares using file-id
Given user "Alice" has uploaded a file inside space "Alice Hansen" with content "some content" to "textfile.txt"
And we save it into "FILEID"
And user "Alice" has created a share inside of space "Alice Hansen" with settings:
| path | textfile.txt |
| shareWith | Brian |
| role | viewer |
When user "Brian" locks file using file-id path "<dav-path>" using the WebDAV API setting the following properties
| lockscope | exclusive |
Then the HTTP status code should be "403"

View File

@@ -3439,7 +3439,7 @@ class SpacesContext implements Context {
*/
public function userSendsPropfindRequestToSpace(string $user, string $spaceName, ?string $resource = ""): void {
$this->setSpaceIDByName($user, $spaceName);
$properties = ['oc:permissions','oc:file-parent','oc:fileid','oc:share-types','oc:privatelink','d:resourcetype','oc:size','oc:name','d:getcontenttype', 'oc:tags'];
$properties = ['oc:permissions','oc:file-parent','oc:fileid','oc:share-types','oc:privatelink','d:resourcetype','oc:size','oc:name','d:getcontenttype','oc:tags','d:lockdiscovery','d:activelock'];
$this->featureContext->setResponse(
WebDavHelper::propfind(
$this->featureContext->getBaseUrl(),
@@ -3473,6 +3473,7 @@ class SpacesContext implements Context {
/**
* @Then /^the "([^"]*)" response to user "([^"]*)" should contain a mountpoint "([^"]*)" with these key and value pairs:$/
* @Then /^the "([^"]*)" response to user "([^"]*)" should contain a space "([^"]*)" with these key and value pairs:$/
*
* @param string $method # method should be either PROPFIND or REPORT
* @param string $user
@@ -3540,6 +3541,18 @@ class SpacesContext implements Context {
$actualTags = \sort($actualTags);
Assert::assertEquals($expectedTags, $actualTags, "wrong $findItem in the response");
break;
case "d:lockdiscovery/d:activelock/d:timeout":
if ($value === "Infinity") {
Assert::assertEquals($value, $responseValue, "wrong $findItem in the response");
} else {
// some time may be required between a lock and propfind request.
$responseValue = explode('-', $responseValue);
$responseValue = \intval($responseValue[1]);
$value = explode('-', $value);
$value = \intval($value[1]);
Assert::assertTrue($responseValue >= ($value - 3));
}
break;
default:
Assert::assertEquals($value, $responseValue, "wrong $findItem in the response");
break;

View File

@@ -23,13 +23,12 @@
use Behat\Behat\Context\Context;
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
use Behat\Gherkin\Node\TableNode;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\GuzzleException;
use PHPUnit\Framework\Assert;
use TestHelpers\HttpRequestHelper;
use TestHelpers\OcsApiHelper;
use TestHelpers\WebDavHelper;
use Psr\Http\Message\ResponseInterface;
use TestHelpers\OcisHelper;
require_once 'bootstrap.php';
@@ -39,6 +38,7 @@ require_once 'bootstrap.php';
class WebDavLockingContext implements Context {
private FeatureContext $featureContext;
private PublicWebDavContext $publicWebDavContext;
private SpacesContext $spacesContext;
/**
*
@@ -76,10 +76,12 @@ class WebDavLockingContext implements Context {
= "<?xml version='1.0' encoding='UTF-8'?>" .
"<d:lockinfo xmlns:d='DAV:'> ";
$headers = [];
$this->featureContext->verifyTableNodeRows($properties, [], ['lockscope', 'depth', 'timeout']);
// depth is only 0 or infinity. We don't need to set it more, as there is no lock for the folder
$this->featureContext->verifyTableNodeRows($properties, [], ['lockscope', 'timeout']);
$propertiesRows = $properties->getRowsHash();
foreach ($propertiesRows as $property => $value) {
if ($property === "depth" || $property === "timeout") {
if ($property === "timeout") {
//properties that are set in the header not in the xml
$headers[$property] = $value;
} else {
@@ -113,7 +115,62 @@ class WebDavLockingContext implements Context {
}
/**
* @When user :user locks file/folder :file using the WebDAV API setting the following properties
*
* @param string $user
* @param string $fullUrl
* @param TableNode $properties table with no heading with | property | value |
* @param boolean $expectToSucceed
*
* @return void
*/
private function lockFileInSpace(
string $user,
string $fullUrl,
TableNode $properties,
bool $expectToSucceed = true
):ResponseInterface {
$body
= "<?xml version='1.0' encoding='UTF-8'?>" .
"<d:lockinfo xmlns:d='DAV:'> ";
$headers = [];
// depth is only 0 or infinity. We don't need to set it more, as there is no lock for the folder
$this->featureContext->verifyTableNodeRows($properties, [], ['lockscope', 'timeout']);
$propertiesRows = $properties->getRowsHash();
foreach ($propertiesRows as $property => $value) {
if ($property === "timeout") {
//properties that are set in the header not in the xml
$headers[$property] = $value;
} else {
$body .= "<d:$property><d:$value/></d:$property>";
}
}
$body .= "</d:lockinfo>";
$response = HttpRequestHelper::sendRequest(
$fullUrl,
$this->featureContext->getStepLineRef(),
"LOCK",
$this->featureContext->getActualUsername($user),
$this->featureContext->getPasswordForUser($user),
$headers,
$body
);
$responseXml = $this->featureContext->getResponseXml($response, __METHOD__);
$xmlPart = $responseXml->xpath("//d:locktoken/d:href");
if (isset($xmlPart[0])) {
$this->tokenOfLastLock[$user] = (string) $xmlPart[0];
} else {
if ($expectToSucceed === true) {
Assert::fail("could not find lock token after the last lock");
}
}
return $response;
}
/**
* @When user :user locks file :file using the WebDAV API setting the following properties
* @When user :user tries to lock file :file using the WebDAV API setting the following properties
*
* @param string $user
* @param string $file
@@ -127,7 +184,39 @@ class WebDavLockingContext implements Context {
}
/**
* @Given user :user has locked file/folder :file setting the following properties
* @When user :user locks file :file inside the space :space using the WebDAV API setting the following properties
*
* @param string $user
* @param string $file
* @param string $space
* @param TableNode $properties table with no heading with | property | value |
*
* @return void
*/
public function lockFileInProjectSpaceUsingWebDavAPI(string $user, string $file, string $space, TableNode $properties) {
$spaceId = $this->spacesContext->getSpaceIdByName($user, $space);
$fullUrl = $this->featureContext->getBaseUrl() . '/dav/spaces/' . $spaceId . '/' . $file;
$response = $this->lockFileInSpace($user, $fullUrl, $properties);
$this->featureContext->setResponse($response);
}
/**
* @When user :user locks file using file-id path :path using the WebDAV API setting the following properties
*
* @param string $user
* @param string $filePath
* @param TableNode $properties table with no heading with | property | value |
*
* @return void
*/
public function lockFileUsingFileIdUsingWebDavAPI(string $user, string $filePath, TableNode $properties) {
$fullUrl = $this->featureContext->getBaseUrl() . $filePath;
$response = $this->lockFileInSpace($user, $fullUrl, $properties);
$this->featureContext->setResponse($response);
}
/**
* @Given user :user has locked file :file setting the following properties
*
* @param string $user
* @param string $file
@@ -221,7 +310,7 @@ class WebDavLockingContext implements Context {
}
/**
* @When user :user unlocks the last created lock of file/folder :file using the WebDAV API
* @When user :user unlocks the last created lock of file :file using the WebDAV API
*
* @param string $user
* @param string $file
@@ -239,7 +328,7 @@ class WebDavLockingContext implements Context {
}
/**
* @When user :user unlocks file/folder :itemToUnlock with the last created lock of file/folder :itemToUseLockOf using the WebDAV API
* @When user :user unlocks file :itemToUnlock with the last created lock of file :itemToUseLockOf using the WebDAV API
*
* @param string $user
* @param string $itemToUnlock
@@ -262,7 +351,7 @@ class WebDavLockingContext implements Context {
}
/**
* @When user :user unlocks file/folder :itemToUnlock with the last created public lock of file/folder :itemToUseLockOf using the WebDAV API
* @When user :user unlocks file :itemToUnlock with the last created public lock of file :itemToUseLockOf using the WebDAV API
*
* @param string $user
* @param string $itemToUnlock
@@ -327,7 +416,7 @@ class WebDavLockingContext implements Context {
}
/**
* @Given user :user has unlocked file/folder :itemToUnlock with the last created lock of file/folder :itemToUseLockOf of user :lockOwner using the WebDAV API
* @Given user :user has unlocked file :itemToUnlock with the last created lock of file :itemToUseLockOf of user :lockOwner using the WebDAV API
*
* @param string $user
* @param string $itemToUnlock
@@ -409,7 +498,7 @@ class WebDavLockingContext implements Context {
}
/**
* @When user :user unlocks file/folder :itemToUnlock with the last created lock of file/folder :itemToUseLockOf of user :lockOwner using the WebDAV API
* @When user :user unlocks file :itemToUnlock with the last created lock of file :itemToUseLockOf of user :lockOwner using the WebDAV API
*
* @param string $user
* @param string $itemToUnlock
@@ -434,7 +523,7 @@ class WebDavLockingContext implements Context {
}
/**
* @When the public unlocks file/folder :itemToUnlock with the last created lock of file/folder :itemToUseLockOf of user :lockOwner using the WebDAV API
* @When the public unlocks file :itemToUnlock with the last created lock of file :itemToUseLockOf of user :lockOwner using the WebDAV API
*
* @param string $itemToUnlock
* @param string $lockOwner
@@ -459,7 +548,7 @@ class WebDavLockingContext implements Context {
}
/**
* @When the public unlocks file/folder :itemToUnlock using the WebDAV API
* @When the public unlocks file :itemToUnlock using the WebDAV API
*
* @param string $itemToUnlock
*
@@ -657,7 +746,7 @@ class WebDavLockingContext implements Context {
}
/**
* @Then :count locks should be reported for file/folder :file of user :user by the WebDAV API
* @Then :count locks should be reported for file :file of user :user by the WebDAV API
*
* @param int $count
* @param string $file
@@ -675,57 +764,6 @@ class WebDavLockingContext implements Context {
);
}
/**
* @Then group :expectedGroup should exist as a lock breaker group
*
* @param string $expectedGroup
*
* @return void
*
* @throws Exception
*/
public function groupShouldExistAsLockBreakerGroups(string $expectedGroup) {
$baseUrl = $this->featureContext->getBaseUrl();
$admin = $this->featureContext->getAdminUsername();
$password = $this->featureContext->getAdminPassword();
$ocsApiVersion = $this->featureContext->getOcsApiVersion();
$response = OcsApiHelper::sendRequest(
$baseUrl,
$admin,
$password,
'GET',
"/apps/testing/api/v1/app/core/lock-breaker-groups",
$this->featureContext->getStepLineRef(),
(string) $ocsApiVersion
);
$responseXml = HttpRequestHelper::getResponseXml($response, __METHOD__)->data->element;
$lockbreakergroup = trim(\json_decode(\json_encode($responseXml), true)['value'], '\'[]"');
$actualgroup = explode("\",\"", $lockbreakergroup);
if (!\in_array($expectedGroup, $actualgroup)) {
Assert::fail("could not find group '$expectedGroup' in lock breakers group");
}
}
/**
* @Then following groups should exist as lock breaker groups
*
* @param TableNode $table
*
* @return void
*
* @throws Exception
*/
public function followingGroupShouldExistAsLockBreakerGroups(TableNode $table) {
$this->featureContext->verifyTableNodeColumns($table, ["groups"]);
$paths = $table->getHash();
foreach ($paths as $group) {
$this->groupShouldExistAsLockBreakerGroups($group["groups"]);
}
}
/**
* This will run before EVERY scenario.
* It will set the properties for this object.
@@ -742,5 +780,8 @@ class WebDavLockingContext implements Context {
// Get all the contexts you need in this context
$this->featureContext = $environment->getContext('FeatureContext');
$this->publicWebDavContext = $environment->getContext('PublicWebDavContext');
if (!OcisHelper::isTestingOnReva()) {
$this->spacesContext = $environment->getContext('SpacesContext');
}
}
}