diff options
author | Robin Appelman <icewind@owncloud.com> | 2015-08-07 16:04:27 +0200 |
---|---|---|
committer | Robin Appelman <icewind@owncloud.com> | 2015-08-11 14:43:46 +0200 |
commit | 8c5302847b9ac3d491c1b62411e62f509573fe7a (patch) | |
tree | 1be1a8cb26b50ad3aafc4bb7d96f656a0841da64 /tests | |
parent | 6e4a79f8529a69b846f73257cc581d2b80f7762d (diff) | |
download | nextcloud-server-8c5302847b9ac3d491c1b62411e62f509573fe7a.tar.gz nextcloud-server-8c5302847b9ac3d491c1b62411e62f509573fe7a.zip |
add test framework for doing full request webdav tests
Diffstat (limited to 'tests')
-rw-r--r-- | tests/lib/connector/sabre/requesttest/auth.php | 69 | ||||
-rw-r--r-- | tests/lib/connector/sabre/requesttest/exceptionplugin.php | 32 | ||||
-rw-r--r-- | tests/lib/connector/sabre/requesttest/requesttest.php | 174 | ||||
-rw-r--r-- | tests/lib/connector/sabre/requesttest/sapi.php | 53 | ||||
-rw-r--r-- | tests/lib/connector/sabre/requesttest/uploadtest.php | 88 |
5 files changed, 416 insertions, 0 deletions
diff --git a/tests/lib/connector/sabre/requesttest/auth.php b/tests/lib/connector/sabre/requesttest/auth.php new file mode 100644 index 00000000000..7cab4da5264 --- /dev/null +++ b/tests/lib/connector/sabre/requesttest/auth.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Connector\Sabre\RequestTest; + +use Sabre\DAV\Auth\Backend\BackendInterface; + +class Auth implements BackendInterface { + /** + * @var string + */ + private $user; + + /** + * @var string + */ + private $password; + + /** + * Auth constructor. + * + * @param string $user + * @param string $password + */ + public function __construct($user, $password) { + $this->user = $user; + $this->password = $password; + } + + + /** + * Authenticates the user based on the current request. + * + * If authentication is successful, true must be returned. + * If authentication fails, an exception must be thrown. + * + * @param \Sabre\DAV\Server $server + * @param string $realm + * @return bool + */ + function authenticate(\Sabre\DAV\Server $server, $realm) { + $userSession = \OC::$server->getUserSession(); + $result = $userSession->login($this->user, $this->password); + if ($result) { + //we need to pass the user name, which may differ from login name + $user = $userSession->getUser()->getUID(); + \OC_Util::setupFS($user); + //trigger creation of user home and /files folder + \OC::$server->getUserFolder($user); + } + return $result; + } + + /** + * Returns information about the currently logged in username. + * + * If nobody is currently logged in, this method should return null. + * + * @return string|null + */ + function getCurrentUser() { + return $this->user; + } +} diff --git a/tests/lib/connector/sabre/requesttest/exceptionplugin.php b/tests/lib/connector/sabre/requesttest/exceptionplugin.php new file mode 100644 index 00000000000..2b9e5d6d46d --- /dev/null +++ b/tests/lib/connector/sabre/requesttest/exceptionplugin.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Connector\Sabre\RequestTest; + +use Sabre\DAV\Exception; + +class ExceptionPlugin extends \OC\Connector\Sabre\ExceptionLoggerPlugin { + /** + * @var \Exception[] + */ + protected $exceptions = []; + + public function logException(\Exception $ex) { + $exceptionClass = get_class($ex); + if (!isset($this->nonFatalExceptions[$exceptionClass])) { + $this->exceptions[] = $ex; + } + } + + /** + * @return \Exception[] + */ + public function getExceptions() { + return $this->exceptions; + } +} diff --git a/tests/lib/connector/sabre/requesttest/requesttest.php b/tests/lib/connector/sabre/requesttest/requesttest.php new file mode 100644 index 00000000000..7a4f44ee71a --- /dev/null +++ b/tests/lib/connector/sabre/requesttest/requesttest.php @@ -0,0 +1,174 @@ +<?php +/** + * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Connector\Sabre\RequestTest; + +use OC\Connector\Sabre\Server; +use OC\Files\Mount\MountPoint; +use OC\Files\Storage\Temporary; +use OC\Files\View; +use OCP\IUser; +use Sabre\HTTP\Request; +use Test\TestCase; + +abstract class RequestTest extends TestCase { + /** + * @var \OC_User_Dummy + */ + protected $userBackend; + + /** + * @var \OCP\Files\Config\IMountProvider[] + */ + protected $mountProviders; + + protected function getStream($string) { + $stream = fopen('php://temp', 'r+'); + fwrite($stream, $string); + fseek($stream, 0); + return $stream; + } + + /** + * @param $userId + * @param $storages + * @return \OCP\Files\Config\IMountProvider + */ + protected function getMountProvider($userId, $storages) { + $mounts = []; + foreach ($storages as $mountPoint => $storage) { + $mounts[] = new MountPoint($storage, $mountPoint); + } + $provider = $this->getMock('\OCP\Files\Config\IMountProvider'); + $provider->expects($this->any()) + ->method('getMountsForUser') + ->will($this->returnCallback(function (IUser $user) use ($userId, $mounts) { + if ($user->getUID() === $userId) { + return $mounts; + } else { + return []; + } + })); + return $provider; + } + + protected function setUp() { + $this->userBackend = new \OC_User_Dummy(); + \OC::$server->getUserManager()->registerBackend($this->userBackend); + } + + protected function tearDown() { + \OC::$server->getUserManager()->removeBackend($this->userBackend); + } + + protected function setupUser($name, $password) { + $this->userBackend->createUser($name, $password); + \OC::$server->getMountProviderCollection()->registerProvider($this->getMountProvider($name, [ + '/' . $name => new Temporary() + ])); + $this->loginAsUser($name); + return new View('/' . $name . '/files'); + } + + /** + * @param \OC\Files\View $view the view to run the webdav server against + * @param string $user + * @param string $password + * @param string $method + * @param string $url + * @param resource|string|null $body + * @param array|null $headers + * @return \Sabre\HTTP\Response + */ + protected function request($view, $user, $password, $method, $url, $body = null, $headers = null) { + if (is_string($body)) { + $body = $this->getStream($body); + } + $this->logout(); + $exceptionPlugin = new ExceptionPlugin('webdav', null); + $server = $this->getSabreServer($view, $user, $password, $exceptionPlugin); + $request = new Request($method, $url, $headers, $body); + + // since sabre catches all exceptions we need to save them and throw them from outside the sabre server + + $originalServer = $_SERVER; + + if (is_array($headers)) { + foreach ($headers as $header => $value) { + $_SERVER['HTTP_' . strtoupper(str_replace('-', '_', $header))] = $value; + } + } + + $result = $this->makeRequest($server, $request); + + foreach ($exceptionPlugin->getExceptions() as $exception) { + throw $exception; + } + $_SERVER = $originalServer; + return $result; + } + + /** + * @param Server $server + * @param Request $request + * @return \Sabre\HTTP\Response + */ + protected function makeRequest(Server $server, Request $request) { + $sapi = new Sapi($request); + $server->sapi = $sapi; + $server->httpRequest = $request; + $server->exec(); + return $sapi->getResponse(); + } + + /** + * @param View $view + * @param string $user + * @param string $password + * @param ExceptionPlugin $exceptionPlugin + * @return Server + */ + protected function getSabreServer(View $view, $user, $password, ExceptionPlugin $exceptionPlugin) { + $authBackend = new Auth($user, $password); + $objectTree = new \OC\Connector\Sabre\ObjectTree(); + $server = new \OC\Connector\Sabre\Server($objectTree); + + $server->setBaseUri('/'); + + // Load plugins + $server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend, 'oc-test')); + $server->addPlugin(new \OC\Connector\Sabre\DummyGetResponsePlugin()); + $server->addPlugin(new \OC\Connector\Sabre\FilesPlugin($objectTree)); + $server->addPlugin($exceptionPlugin); + + // wait with registering these until auth is handled and the filesystem is setup + $server->on('beforeMethod', function () use ($server, $objectTree, $view) { + $rootInfo = $view->getFileInfo(''); + + // Create ownCloud Dir + $mountManager = \OC\Files\Filesystem::getMountManager(); + $rootDir = new \OC\Connector\Sabre\Directory($view, $rootInfo); + $objectTree->init($rootDir, $view, $mountManager); + + $server->addPlugin(new \OC\Connector\Sabre\QuotaPlugin($view)); + + // custom properties plugin must be the last one + $server->addPlugin( + new \Sabre\DAV\PropertyStorage\Plugin( + new \OC\Connector\Sabre\CustomPropertiesBackend( + $objectTree, + \OC::$server->getDatabaseConnection(), + \OC::$server->getUserSession()->getUser() + ) + ) + ); + $server->addPlugin(new \OC\Connector\Sabre\CopyEtagHeaderPlugin()); + }, 30); // priority 30: after auth (10) and acl(20), before lock(50) and handling the request + return $server; + } +} diff --git a/tests/lib/connector/sabre/requesttest/sapi.php b/tests/lib/connector/sabre/requesttest/sapi.php new file mode 100644 index 00000000000..7072b8bd286 --- /dev/null +++ b/tests/lib/connector/sabre/requesttest/sapi.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Connector\Sabre\RequestTest; + +use Sabre\HTTP\Request; +use Sabre\HTTP\Response; + +class Sapi { + /** + * @var \Sabre\HTTP\Request + */ + private $request; + + /** + * @var \Sabre\HTTP\Response + */ + private $response; + + /** + * This static method will create a new Request object, based on the + * current PHP request. + * + * @return \Sabre\HTTP\Request + */ + public function getRequest() { + return $this->request; + } + + public function __construct(Request $request) { + $this->request = $request; + } + + /** + * @param \Sabre\HTTP\Response $response + * @return void + */ + public function sendResponse(Response $response) { + $this->response = $response; + } + + /** + * @return \Sabre\HTTP\Response + */ + public function getResponse() { + return $this->response; + } +} diff --git a/tests/lib/connector/sabre/requesttest/uploadtest.php b/tests/lib/connector/sabre/requesttest/uploadtest.php new file mode 100644 index 00000000000..2cc912d07f2 --- /dev/null +++ b/tests/lib/connector/sabre/requesttest/uploadtest.php @@ -0,0 +1,88 @@ +<?php +/** + * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Connector\Sabre\RequestTest; + +class UploadTest extends RequestTest { + public function testBasicUpload() { + $user = $this->getUniqueID(); + $view = $this->setupUser($user, 'pass'); + + $this->assertFalse($view->file_exists('foo.txt')); + $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd'); + + $this->assertEquals(201, $response->getStatus()); + $this->assertTrue($view->file_exists('foo.txt')); + $this->assertEquals('asd', $view->file_get_contents('foo.txt')); + } + + public function testUploadOverWrite() { + $user = $this->getUniqueID(); + $view = $this->setupUser($user, 'pass'); + + $view->file_put_contents('foo.txt', 'bar'); + + $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd'); + + $this->assertEquals(204, $response->getStatus()); + $this->assertEquals('asd', $view->file_get_contents('foo.txt')); + } + + public function testChunkedUpload() { + $user = $this->getUniqueID(); + $view = $this->setupUser($user, 'pass'); + + $this->assertFalse($view->file_exists('foo.txt')); + $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']); + + $this->assertEquals(201, $response->getStatus()); + $this->assertFalse($view->file_exists('foo.txt')); + + $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']); + + $this->assertEquals(201, $response->getStatus()); + $this->assertTrue($view->file_exists('foo.txt')); + + $this->assertEquals('asdbar', $view->file_get_contents('foo.txt')); + } + + public function testChunkedUploadOverWrite() { + $user = $this->getUniqueID(); + $view = $this->setupUser($user, 'pass'); + + $view->file_put_contents('foo.txt', 'bar'); + $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']); + + $this->assertEquals(201, $response->getStatus()); + $this->assertEquals('bar', $view->file_get_contents('foo.txt')); + + $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']); + + $this->assertEquals(201, $response->getStatus()); + + $this->assertEquals('asdbar', $view->file_get_contents('foo.txt')); + } + + public function testChunkedUploadOutOfOrder() { + $user = $this->getUniqueID(); + $view = $this->setupUser($user, 'pass'); + + $this->assertFalse($view->file_exists('foo.txt')); + $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']); + + $this->assertEquals(201, $response->getStatus()); + $this->assertFalse($view->file_exists('foo.txt')); + + $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']); + + $this->assertEquals(201, $response->getStatus()); + $this->assertTrue($view->file_exists('foo.txt')); + + $this->assertEquals('asdbar', $view->file_get_contents('foo.txt')); + } +} |