diff options
Diffstat (limited to 'tests/lib')
67 files changed, 4069 insertions, 901 deletions
diff --git a/tests/lib/activitymanager.php b/tests/lib/activitymanager.php index 6a5af7b259b..d227c05d827 100644 --- a/tests/lib/activitymanager.php +++ b/tests/lib/activitymanager.php @@ -31,16 +31,6 @@ class Test_ActivityManager extends \Test\TestCase { $this->assertEquals(2, sizeof($result)); } - public function testFilterNotificationTypes() { - $result = $this->activityManager->filterNotificationTypes(array('NT0', 'NT1', 'NT2', 'NT3'), 'FILTER1'); - $this->assertTrue(is_array($result)); - $this->assertEquals(3, sizeof($result)); - - $result = $this->activityManager->filterNotificationTypes(array('NT0', 'NT1', 'NT2', 'NT3'), 'FILTER2'); - $this->assertTrue(is_array($result)); - $this->assertEquals(4, sizeof($result)); - } - public function testDefaultTypes() { $result = $this->activityManager->getDefaultTypes('stream'); $this->assertTrue(is_array($result)); @@ -51,6 +41,14 @@ class Test_ActivityManager extends \Test\TestCase { $this->assertEquals(0, sizeof($result)); } + public function testTypeIcon() { + $result = $this->activityManager->getTypeIcon('NT1'); + $this->assertEquals('icon-nt-one', $result); + + $result = $this->activityManager->getTypeIcon('NT2'); + $this->assertEquals('', $result); + } + public function testTranslate() { $result = $this->activityManager->translate('APP0', '', '', array(), false, false, 'en'); $this->assertEquals('Stupid translation', $result); @@ -67,14 +65,6 @@ class Test_ActivityManager extends \Test\TestCase { $this->assertFalse($result); } - public function testTypeIcon() { - $result = $this->activityManager->getTypeIcon('NT1'); - $this->assertEquals('icon-nt-one', $result); - - $result = $this->activityManager->getTypeIcon('NT2'); - $this->assertEquals('', $result); - } - public function testGroupParameter() { $result = $this->activityManager->getGroupParameter(array()); $this->assertEquals(5, $result); @@ -90,15 +80,27 @@ class Test_ActivityManager extends \Test\TestCase { $result = $this->activityManager->isFilterValid('fv01'); $this->assertTrue($result); - $result = $this->activityManager->isFilterValid('FV2'); + $result = $this->activityManager->isFilterValid('InvalidFilter'); $this->assertFalse($result); } + public function testFilterNotificationTypes() { + $result = $this->activityManager->filterNotificationTypes(array('NT0', 'NT1', 'NT2', 'NT3'), 'fv01'); + $this->assertTrue(is_array($result)); + $this->assertEquals(3, sizeof($result)); + + $result = $this->activityManager->filterNotificationTypes(array('NT0', 'NT1', 'NT2', 'NT3'), 'InvalidFilter'); + $this->assertTrue(is_array($result)); + $this->assertEquals(4, sizeof($result)); + } + public function testQueryForFilter() { + // Register twice, to test the created sql part $this->activityManager->registerExtension(function() { return new SimpleExtension(); }); - $result = $this->activityManager->getQueryForFilter('filter1'); + + $result = $this->activityManager->getQueryForFilter('fv01'); $this->assertEquals( array( ' and ((`app` = ? and `message` like ?) or (`app` = ? and `message` like ?))', @@ -106,8 +108,8 @@ class Test_ActivityManager extends \Test\TestCase { ), $result ); - $result = $this->activityManager->isFilterValid('filter2'); - $this->assertFalse($result); + $result = $this->activityManager->getQueryForFilter('InvalidFilter'); + $this->assertEquals(array(null, null), $result); } } @@ -117,13 +119,6 @@ class SimpleExtension implements \OCP\Activity\IExtension { return array('NT1', 'NT2'); } - public function filterNotificationTypes($types, $filter) { - if ($filter === 'FILTER1') { - unset($types[0]); - } - return $types; - } - public function getDefaultTypes($method) { if ($method === 'stream') { return array('DT0'); @@ -132,6 +127,13 @@ class SimpleExtension implements \OCP\Activity\IExtension { return array(); } + public function getTypeIcon($type) { + if ($type === 'NT1') { + return 'icon-nt-one'; + } + return ''; + } + public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) { if ($app === 'APP0') { return "Stupid translation"; @@ -148,13 +150,6 @@ class SimpleExtension implements \OCP\Activity\IExtension { return false; } - public function getTypeIcon($type) { - if ($type === 'NT1') { - return 'icon-nt-one'; - } - return ''; - } - public function getGroupParameter($activity) { return 5; } @@ -174,8 +169,15 @@ class SimpleExtension implements \OCP\Activity\IExtension { return false; } + public function filterNotificationTypes($types, $filter) { + if ($filter === 'fv01') { + unset($types[0]); + } + return $types; + } + public function getQueryForFilter($filter) { - if ($filter === 'filter1') { + if ($filter === 'fv01') { return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%')); } @@ -189,11 +191,11 @@ class NoOpExtension implements \OCP\Activity\IExtension { return false; } - public function filterNotificationTypes($types, $filter) { + public function getDefaultTypes($method) { return false; } - public function getDefaultTypes($method) { + public function getTypeIcon($type) { return false; } @@ -205,10 +207,6 @@ class NoOpExtension implements \OCP\Activity\IExtension { return false; } - public function getTypeIcon($type) { - return false; - } - public function getGroupParameter($activity) { return false; } @@ -221,6 +219,10 @@ class NoOpExtension implements \OCP\Activity\IExtension { return false; } + public function filterNotificationTypes($types, $filter) { + return false; + } + public function getQueryForFilter($filter) { return false; } diff --git a/tests/lib/app.php b/tests/lib/app.php index 0c0eb28b3ba..86a407c1a95 100644 --- a/tests/lib/app.php +++ b/tests/lib/app.php @@ -1,4 +1,5 @@ <?php + /** * Copyright (c) 2012 Bernhard Posselt <dev@bernhard-posselt.com> * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com> @@ -6,11 +7,8 @@ * later. * See the COPYING-README file. */ - class Test_App extends \Test\TestCase { - private $oldAppConfigService; - const TEST_USER1 = 'user1'; const TEST_USER2 = 'user2'; const TEST_USER3 = 'user3'; @@ -398,10 +396,9 @@ class Test_App extends \Test\TestCase { 'appforgroup12' => '["group2","group1"]', ) ) - ); + ); $apps = \OC_App::getEnabledApps(true, $forceAll); - $this->assertEquals($expectedApps, $apps); $this->restoreAppConfig(); \OC_User::setUserId(null); @@ -412,6 +409,8 @@ class Test_App extends \Test\TestCase { $group1->delete(); $group2->delete(); + + $this->assertEquals($expectedApps, $apps); } /** @@ -432,7 +431,7 @@ class Test_App extends \Test\TestCase { 'app2' => 'no', ) ) - ); + ); $apps = \OC_App::getEnabledApps(true); $this->assertEquals(array('files', 'app3'), $apps); @@ -447,30 +446,6 @@ class Test_App extends \Test\TestCase { $user1->delete(); } - /** - * Tests that the apps list is re-requested (not cached) when - * no user is set. - */ - public function testEnabledAppsNoCache() { - $this->setupAppConfigMock()->expects($this->exactly(2)) - ->method('getValues') - ->will($this->returnValue( - array( - 'app3' => 'yes', - 'app2' => 'no', - ) - ) - ); - - $apps = \OC_App::getEnabledApps(true); - $this->assertEquals(array('files', 'app3'), $apps); - - // mock should be called again here - $apps = \OC_App::getEnabledApps(false); - $this->assertEquals(array('files', 'app3'), $apps); - - $this->restoreAppConfig(); - } private function setupAppConfigMock() { $appConfig = $this->getMock( @@ -487,22 +462,27 @@ class Test_App extends \Test\TestCase { /** * Register an app config mock for testing purposes. + * * @param $appConfig app config mock */ private function registerAppConfig($appConfig) { - $this->oldAppConfigService = \OC::$server->query('AppConfig'); \OC::$server->registerService('AppConfig', function ($c) use ($appConfig) { return $appConfig; }); + \OC::$server->registerService('AppManager', function (\OC\Server $c) use ($appConfig) { + return new \OC\App\AppManager($c->getUserSession(), $appConfig, $c->getGroupManager()); + }); } /** * Restore the original app config service. */ private function restoreAppConfig() { - $oldService = $this->oldAppConfigService; - \OC::$server->registerService('AppConfig', function ($c) use ($oldService){ - return $oldService; + \OC::$server->registerService('AppConfig', function ($c) { + return new \OC\AppConfig(\OC_DB::getConnection()); + }); + \OC::$server->registerService('AppManager', function (\OC\Server $c) { + return new \OC\App\AppManager($c->getUserSession(), $c->getAppConfig(), $c->getGroupManager()); }); // Remove the cache of the mocked apps list with a forceRefresh diff --git a/tests/lib/app/codechecker.php b/tests/lib/app/codechecker.php new file mode 100644 index 00000000000..64403fd0f23 --- /dev/null +++ b/tests/lib/app/codechecker.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright (c) 2015 Thomas Müller <deepdiver@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\App; + +use OC; + +class CodeChecker extends \Test\TestCase { + + /** + * @dataProvider providesFilesToCheck + * @param $expectedErrors + * @param $fileToVerify + */ + public function testFindInvalidUsage($expectedErrorToken, $expectedErrorCode, $fileToVerify) { + $checker = new OC\App\CodeChecker(); + $errors = $checker->analyseFile(OC::$SERVERROOT . "/tests/data/app/code-checker/$fileToVerify"); + + $this->assertEquals(1, count($errors)); + $this->assertEquals($expectedErrorCode, $errors[0]['errorCode']); + $this->assertEquals($expectedErrorToken, $errors[0]['disallowedToken']); + } + + public function providesFilesToCheck() { + return [ + ['OC_Hook', 1000, 'test-extends.php'], + ['oC_Avatar', 1001, 'test-implements.php'], + ['OC_App', 1002, 'test-static-call.php'], + ['OC_API', 1003, 'test-const.php'], + ['OC_AppConfig', 1004, 'test-new.php'], + ]; + } +} diff --git a/tests/lib/app/dependencyanalyzer.php b/tests/lib/app/dependencyanalyzer.php index a79995b78b3..d73bac5a2a7 100644 --- a/tests/lib/app/dependencyanalyzer.php +++ b/tests/lib/app/dependencyanalyzer.php @@ -52,7 +52,7 @@ class DependencyAnalyzer extends \PHPUnit_Framework_TestCase { })); $this->platformMock->expects($this->any()) ->method('getOcVersion') - ->will( $this->returnValue('8.0.1')); + ->will( $this->returnValue('8.0.2')); $this->l10nMock = $this->getMockBuilder('\OCP\IL10N') ->disableOriginalConstructor() @@ -183,8 +183,12 @@ class DependencyAnalyzer extends \PHPUnit_Framework_TestCase { return array( // no version -> no missing dependency array(array(), null), + array(array(), array('@attributes' => array('min-version' => '8', 'max-version' => '8'))), + array(array(), array('@attributes' => array('min-version' => '8.0', 'max-version' => '8.0'))), + array(array(), array('@attributes' => array('min-version' => '8.0.2', 'max-version' => '8.0.2'))), + array(array('ownCloud 8.0.3 or higher is required.'), array('@attributes' => array('min-version' => '8.0.3'))), array(array('ownCloud 9 or higher is required.'), array('@attributes' => array('min-version' => '9'))), - array(array('ownCloud with a version lower than 5.1.2 is required.'), array('@attributes' => array('max-version' => '5.1.2'))), + array(array('ownCloud with a version lower than 8.0.1 is required.'), array('@attributes' => array('max-version' => '8.0.1'))), ); } @@ -208,7 +212,17 @@ class DependencyAnalyzer extends \PHPUnit_Framework_TestCase { array(array('@attributes' => array('min-version' => '100.0'), '@value' => 'curl'))), // curl in version 100.0 does not exist array(array('Library curl with a version lower than 1.0.0 is required - available version 2.3.4.'), - array(array('@attributes' => array('max-version' => '1.0.0'), '@value' => 'curl'))) + array(array('@attributes' => array('max-version' => '1.0.0'), '@value' => 'curl'))), + array(array('Library curl with a version lower than 2.3.3 is required - available version 2.3.4.'), + array(array('@attributes' => array('max-version' => '2.3.3'), '@value' => 'curl'))), + array(array('Library curl with a version higher than 2.3.5 is required - available version 2.3.4.'), + array(array('@attributes' => array('min-version' => '2.3.5'), '@value' => 'curl'))), + array(array(), + array(array('@attributes' => array('min-version' => '2.3.4', 'max-version' => '2.3.4'), '@value' => 'curl'))), + array(array(), + array(array('@attributes' => array('min-version' => '2.3', 'max-version' => '2.3'), '@value' => 'curl'))), + array(array(), + array(array('@attributes' => array('min-version' => '2', 'max-version' => '2'), '@value' => 'curl'))), ); } @@ -244,6 +258,7 @@ class DependencyAnalyzer extends \PHPUnit_Framework_TestCase { array(array(), '5.4', '5.5'), array(array('PHP 5.4.4 or higher is required.'), '5.4.4', null), array(array('PHP with a version lower than 5.4.2 is required.'), null, '5.4.2'), + array(array(), '5.4', '5.4'), ); } } diff --git a/tests/lib/app/manager.php b/tests/lib/app/manager.php index 4c0555b501f..cb41f737469 100644 --- a/tests/lib/app/manager.php +++ b/tests/lib/app/manager.php @@ -192,4 +192,36 @@ class Manager extends \PHPUnit_Framework_TestCase { $appConfig->setValue('test', 'enabled', '["foo"]'); $this->assertTrue($manager->isEnabledForUser('test')); } + + public function testGetInstalledApps() { + $userSession = $this->getMock('\OCP\IUserSession'); + $groupManager = $this->getMock('\OCP\IGroupManager'); + + $appConfig = $this->getAppConfig(); + $manager = new \OC\App\AppManager($userSession, $appConfig, $groupManager); + $appConfig->setValue('test1', 'enabled', 'yes'); + $appConfig->setValue('test2', 'enabled', 'no'); + $appConfig->setValue('test3', 'enabled', '["foo"]'); + $this->assertEquals(['test1', 'test3'], $manager->getInstalledApps()); + } + + public function testGetAppsForUser() { + $userSession = $this->getMock('\OCP\IUserSession'); + $groupManager = $this->getMock('\OCP\IGroupManager'); + + $user = new User('user1', null); + + $groupManager->expects($this->any()) + ->method('getUserGroupIds') + ->with($user) + ->will($this->returnValue(array('foo', 'bar'))); + + $appConfig = $this->getAppConfig(); + $manager = new \OC\App\AppManager($userSession, $appConfig, $groupManager); + $appConfig->setValue('test1', 'enabled', 'yes'); + $appConfig->setValue('test2', 'enabled', 'no'); + $appConfig->setValue('test3', 'enabled', '["foo"]'); + $appConfig->setValue('test4', 'enabled', '["asd"]'); + $this->assertEquals(['test1', 'test3'], $manager->getEnabledAppsForUser($user)); + } } diff --git a/tests/lib/appconfig.php b/tests/lib/appconfig.php index 188721ff92d..ead5b859277 100644 --- a/tests/lib/appconfig.php +++ b/tests/lib/appconfig.php @@ -11,6 +11,12 @@ class Test_Appconfig extends \Test\TestCase { public static function setUpBeforeClass() { parent::setUpBeforeClass(); + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*appconfig` WHERE `appid` = ?'); + $query->execute(array('testapp')); + $query->execute(array('someapp')); + $query->execute(array('123456')); + $query->execute(array('anotherapp')); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*appconfig` VALUES (?, ?, ?)'); $query->execute(array('testapp', 'enabled', 'true')); diff --git a/tests/lib/appframework/AppTest.php b/tests/lib/appframework/AppTest.php index e60f3439f23..05190ca09b5 100644 --- a/tests/lib/appframework/AppTest.php +++ b/tests/lib/appframework/AppTest.php @@ -24,6 +24,9 @@ namespace OC\AppFramework; +use OCP\AppFramework\Http\Response; + + function rrmdir($directory) { $files = array_diff(scandir($directory), array('.','..')); foreach ($files as $file) { @@ -36,9 +39,11 @@ function rrmdir($directory) { return rmdir($directory); } + class AppTest extends \Test\TestCase { private $container; + private $io; private $api; private $controller; private $dispatcher; @@ -62,6 +67,7 @@ class AppTest extends \Test\TestCase { ->disableOriginalConstructor() ->getMock(); + $this->io = $this->getMockBuilder('OCP\\AppFramework\\Http\\IOutput')->getMock(); $this->headers = array('key' => 'value'); $this->output = 'hi'; @@ -70,6 +76,7 @@ class AppTest extends \Test\TestCase { $this->container[$this->controllerName] = $this->controller; $this->container['Dispatcher'] = $this->dispatcher; + $this->container['OCP\\AppFramework\\Http\\IOutput'] = $this->io; $this->container['urlParams'] = array(); $this->appPath = __DIR__ . '/../../../apps/namespacetestapp/appinfo'; @@ -86,14 +93,15 @@ class AppTest extends \Test\TestCase { public function testControllerNameAndMethodAreBeingPassed(){ - $return = array(null, array(), array(), null); + $return = array(null, array(), array(), null, new Response()); $this->dispatcher->expects($this->once()) ->method('dispatch') ->with($this->equalTo($this->controller), $this->equalTo($this->controllerMethod)) ->will($this->returnValue($return)); - $this->expectOutputString(''); + $this->io->expects($this->never()) + ->method('setOutput'); App::main($this->controllerName, $this->controllerMethod, $this->container); @@ -122,26 +130,34 @@ class AppTest extends \Test\TestCase { rrmdir($this->appPath); } - /* - FIXME: this complains about shit headers which are already sent because - of the content length. Would be cool if someone could fix this public function testOutputIsPrinted(){ - $return = array(null, array(), $this->output); + $return = [null, [], [], $this->output, new Response()]; $this->dispatcher->expects($this->once()) ->method('dispatch') ->with($this->equalTo($this->controller), $this->equalTo($this->controllerMethod)) ->will($this->returnValue($return)); - - $this->expectOutputString($this->output); - - App::main($this->controllerName, $this->controllerMethod, array(), - $this->container); + $this->io->expects($this->once()) + ->method('setOutput') + ->with($this->equalTo($this->output)); + App::main($this->controllerName, $this->controllerMethod, $this->container, []); } - */ - // FIXME: if someone manages to test the headers output, I'd be grateful + public function testCallbackIsCalled(){ + $mock = $this->getMockBuilder('OCP\AppFramework\Http\ICallbackResponse') + ->getMock(); + + $return = [null, [], [], $this->output, $mock]; + $this->dispatcher->expects($this->once()) + ->method('dispatch') + ->with($this->equalTo($this->controller), + $this->equalTo($this->controllerMethod)) + ->will($this->returnValue($return)); + $mock->expects($this->once()) + ->method('callback'); + App::main($this->controllerName, $this->controllerMethod, $this->container, []); + } } diff --git a/tests/lib/appframework/controller/ApiControllerTest.php b/tests/lib/appframework/controller/ApiControllerTest.php index 3055fbe0da8..137e5950f67 100644 --- a/tests/lib/appframework/controller/ApiControllerTest.php +++ b/tests/lib/appframework/controller/ApiControllerTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -25,18 +25,20 @@ namespace OCP\AppFramework; use OC\AppFramework\Http\Request; -use OCP\AppFramework\Http\TemplateResponse; class ChildApiController extends ApiController {}; class ApiControllerTest extends \Test\TestCase { - + /** @var ChildApiController */ + protected $controller; public function testCors() { $request = new Request( - array('server' => array('HTTP_ORIGIN' => 'test')) + ['server' => ['HTTP_ORIGIN' => 'test']], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') ); $this->controller = new ChildApiController('app', $request, 'verbs', 'headers', 100); diff --git a/tests/lib/appframework/controller/ControllerTest.php b/tests/lib/appframework/controller/ControllerTest.php index 18d47d00f6b..ccc373f4d59 100644 --- a/tests/lib/appframework/controller/ControllerTest.php +++ b/tests/lib/appframework/controller/ControllerTest.php @@ -66,15 +66,17 @@ class ControllerTest extends \Test\TestCase { parent::setUp(); $request = new Request( - array( - 'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'), - 'post' => array('name' => 'Jane Doe', 'nickname' => 'Janey'), - 'urlParams' => array('name' => 'Johnny Weissmüller'), - 'files' => array('file' => 'filevalue'), - 'env' => array('PATH' => 'daheim'), - 'session' => array('sezession' => 'kein'), + [ + 'get' => ['name' => 'John Q. Public', 'nickname' => 'Joey'], + 'post' => ['name' => 'Jane Doe', 'nickname' => 'Janey'], + 'urlParams' => ['name' => 'Johnny Weissmüller'], + 'files' => ['file' => 'filevalue'], + 'env' => ['PATH' => 'daheim'], + 'session' => ['sezession' => 'kein'], 'method' => 'hi', - ) + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') ); $this->app = $this->getMock('OC\AppFramework\DependencyInjection\DIContainer', @@ -171,11 +173,12 @@ class ControllerTest extends \Test\TestCase { public function testFormatDataResponseJSON() { - $expectedHeaders = array( + $expectedHeaders = [ 'test' => 'something', 'Cache-Control' => 'no-cache, must-revalidate', - 'Content-Type' => 'application/json; charset=utf-8' - ); + 'Content-Type' => 'application/json; charset=utf-8', + 'Content-Security-Policy' => "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'", + ]; $response = $this->controller->customDataResponse(array('hi')); $response = $this->controller->buildResponse($response, 'json'); diff --git a/tests/lib/appframework/controller/OCSControllerTest.php b/tests/lib/appframework/controller/OCSControllerTest.php new file mode 100644 index 00000000000..11a9d45eb92 --- /dev/null +++ b/tests/lib/appframework/controller/OCSControllerTest.php @@ -0,0 +1,143 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2015 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library 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 library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace OCP\AppFramework; + +use OC\AppFramework\Http\Request; +use OCP\AppFramework\Http\DataResponse; + + +class ChildOCSController extends OCSController {} + + +class OCSControllerTest extends \Test\TestCase { + + private $controller; + + public function testCors() { + $request = new Request( + [ + 'server' => [ + 'HTTP_ORIGIN' => 'test', + ], + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); + $controller = new ChildOCSController('app', $request, 'verbs', + 'headers', 100); + + $response = $controller->preflightedCors(); + + $headers = $response->getHeaders(); + + $this->assertEquals('test', $headers['Access-Control-Allow-Origin']); + $this->assertEquals('verbs', $headers['Access-Control-Allow-Methods']); + $this->assertEquals('headers', $headers['Access-Control-Allow-Headers']); + $this->assertEquals('false', $headers['Access-Control-Allow-Credentials']); + $this->assertEquals(100, $headers['Access-Control-Max-Age']); + } + + + public function testXML() { + $controller = new ChildOCSController('app', new Request( + [], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + )); + $expected = "<?xml version=\"1.0\"?>\n" . + "<ocs>\n" . + " <meta>\n" . + " <status>OK</status>\n" . + " <statuscode>400</statuscode>\n" . + " <message>OK</message>\n" . + " </meta>\n" . + " <data>\n" . + " <test>hi</test>\n" . + " </data>\n" . + "</ocs>\n"; + + $params = [ + 'data' => [ + 'test' => 'hi' + ], + 'statuscode' => 400 + ]; + + $out = $controller->buildResponse($params, 'xml')->render(); + $this->assertEquals($expected, $out); + } + + + public function testXMLDataResponse() { + $controller = new ChildOCSController('app', new Request( + [], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + )); + $expected = "<?xml version=\"1.0\"?>\n" . + "<ocs>\n" . + " <meta>\n" . + " <status>OK</status>\n" . + " <statuscode>400</statuscode>\n" . + " <message>OK</message>\n" . + " </meta>\n" . + " <data>\n" . + " <test>hi</test>\n" . + " </data>\n" . + "</ocs>\n"; + + $params = new DataResponse([ + 'data' => [ + 'test' => 'hi' + ], + 'statuscode' => 400 + ]); + + $out = $controller->buildResponse($params, 'xml')->render(); + $this->assertEquals($expected, $out); + } + + + public function testJSON() { + $controller = new ChildOCSController('app', new Request( + [], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + )); + $expected = '{"status":"OK","statuscode":400,"message":"OK",' . + '"totalitems":"","itemsperpage":"","data":{"test":"hi"}}'; + $params = [ + 'data' => [ + 'test' => 'hi' + ], + 'statuscode' => 400 + ]; + + $out = $controller->buildResponse($params, 'json')->render(); + $this->assertEquals($expected, $out); + } + + +} diff --git a/tests/lib/appframework/db/mappertest.php b/tests/lib/appframework/db/mappertest.php index 6ad8cd86bff..8e585c479bb 100644 --- a/tests/lib/appframework/db/mappertest.php +++ b/tests/lib/appframework/db/mappertest.php @@ -24,7 +24,7 @@ namespace OCP\AppFramework\Db; -use \OCP\IDb; +use \OCP\IDBConnection; use Test\AppFramework\Db\MapperTestUtility; /** @@ -42,7 +42,7 @@ class Example extends Entity { class ExampleMapper extends Mapper { - public function __construct(IDb $db){ parent::__construct($db, 'table'); } + public function __construct(IDBConnection $db){ parent::__construct($db, 'table'); } public function find($table, $id){ return $this->findOneQuery($table, $id); } public function findOneEntity($table, $id){ return $this->findEntity($table, $id); } public function findAllEntities($table){ return $this->findEntities($table); } @@ -74,7 +74,7 @@ class MapperTest extends MapperTestUtility { $rows = array( array('hi') ); - $this->setMapperResult($sql, $params, $rows); + $this->setMapperResult($sql, $params, $rows); $this->mapper->find($sql, $params); } @@ -84,7 +84,7 @@ class MapperTest extends MapperTestUtility { $rows = array( array('pre_name' => 'hi') ); - $this->setMapperResult($sql, $params, $rows); + $this->setMapperResult($sql, $params, $rows, null, null, true); $this->mapper->findOneEntity($sql, $params); } @@ -92,7 +92,7 @@ class MapperTest extends MapperTestUtility { $sql = 'hi'; $params = array('jo'); $rows = array(); - $this->setMapperResult($sql, $params, $rows); + $this->setMapperResult($sql, $params, $rows); $this->setExpectedException( '\OCP\AppFramework\Db\DoesNotExistException'); $this->mapper->find($sql, $params); @@ -102,7 +102,7 @@ class MapperTest extends MapperTestUtility { $sql = 'hi'; $params = array('jo'); $rows = array(); - $this->setMapperResult($sql, $params, $rows); + $this->setMapperResult($sql, $params, $rows, null, null, true); $this->setExpectedException( '\OCP\AppFramework\Db\DoesNotExistException'); $this->mapper->findOneEntity($sql, $params); @@ -114,7 +114,7 @@ class MapperTest extends MapperTestUtility { $rows = array( array('jo'), array('ho') ); - $this->setMapperResult($sql, $params, $rows); + $this->setMapperResult($sql, $params, $rows, null, null, true); $this->setExpectedException( '\OCP\AppFramework\Db\MultipleObjectsReturnedException'); $this->mapper->find($sql, $params); @@ -126,7 +126,7 @@ class MapperTest extends MapperTestUtility { $rows = array( array('jo'), array('ho') ); - $this->setMapperResult($sql, $params, $rows); + $this->setMapperResult($sql, $params, $rows, null, null, true); $this->setExpectedException( '\OCP\AppFramework\Db\MultipleObjectsReturnedException'); $this->mapper->findOneEntity($sql, $params); @@ -137,7 +137,7 @@ class MapperTest extends MapperTestUtility { $sql = 'DELETE FROM `*PREFIX*table` WHERE `id` = ?'; $params = array(2); - $this->setMapperResult($sql, $params); + $this->setMapperResult($sql, $params, [], null, null, true); $entity = new Example(); $entity->setId($params[0]); @@ -147,7 +147,7 @@ class MapperTest extends MapperTestUtility { public function testCreate(){ $this->db->expects($this->once()) - ->method('getInsertId') + ->method('lastInsertId') ->with($this->equalTo('*PREFIX*table')) ->will($this->returnValue(3)); $this->mapper = new ExampleMapper($this->db); @@ -159,7 +159,7 @@ class MapperTest extends MapperTestUtility { $entity->setPreName($params[0]); $entity->setEmail($params[1]); - $this->setMapperResult($sql, $params); + $this->setMapperResult($sql, $params, [], null, null, true); $this->mapper->insert($entity); } @@ -167,7 +167,7 @@ class MapperTest extends MapperTestUtility { public function testCreateShouldReturnItemWithCorrectInsertId(){ $this->db->expects($this->once()) - ->method('getInsertId') + ->method('lastInsertId') ->with($this->equalTo('*PREFIX*table')) ->will($this->returnValue(3)); $this->mapper = new ExampleMapper($this->db); @@ -200,7 +200,7 @@ class MapperTest extends MapperTestUtility { $entity->setEmail($params[1]); $entity->setId($params[2]); - $this->setMapperResult($sql, $params); + $this->setMapperResult($sql, $params, [], null, null, true); $this->mapper->update($entity); } @@ -249,7 +249,7 @@ class MapperTest extends MapperTestUtility { $entity = new Example(); $entity->setPreName('hi'); $entity->resetUpdatedFields(); - $this->setMapperResult($sql, array(), $rows); + $this->setMapperResult($sql, array(), $rows, null, null, true); $result = $this->mapper->findAllEntities($sql); $this->assertEquals(array($entity), $result); } diff --git a/tests/lib/appframework/db/mappertestutility.php b/tests/lib/appframework/db/mappertestutility.php index ad7a67a96b1..c87ad528c03 100644 --- a/tests/lib/appframework/db/mappertestutility.php +++ b/tests/lib/appframework/db/mappertestutility.php @@ -31,12 +31,11 @@ namespace Test\AppFramework\Db; abstract class MapperTestUtility extends \Test\TestCase { protected $db; private $query; - private $pdoResult; private $queryAt; private $prepareAt; private $fetchAt; private $iterators; - + /** * Run this function before the actual test to either set or initialize the @@ -46,19 +45,19 @@ abstract class MapperTestUtility extends \Test\TestCase { parent::setUp(); $this->db = $this->getMockBuilder( - '\OCP\IDb') + '\OCP\IDBConnection') ->disableOriginalConstructor() ->getMock(); - $this->query = $this->getMock('Query', array('execute', 'bindValue')); - $this->pdoResult = $this->getMock('Result', array('fetch')); + $this->query = $this->getMock('\PDOStatement'); $this->queryAt = 0; $this->prepareAt = 0; - $this->iterators = array(); + $this->iterators = []; $this->fetchAt = 0; } + /** * Create mocks and set expected results for database queries * @param string $sql the sql query that you expect to receive @@ -69,14 +68,39 @@ abstract class MapperTestUtility extends \Test\TestCase { * will be called on the result */ protected function setMapperResult($sql, $arguments=array(), $returnRows=array(), - $limit=null, $offset=null){ + $limit=null, $offset=null, $expectClose=false){ + if($limit === null && $offset === null) { + $this->db->expects($this->at($this->prepareAt)) + ->method('prepare') + ->with($this->equalTo($sql)) + ->will(($this->returnValue($this->query))); + } elseif($limit !== null && $offset === null) { + $this->db->expects($this->at($this->prepareAt)) + ->method('prepare') + ->with($this->equalTo($sql), $this->equalTo($limit)) + ->will(($this->returnValue($this->query))); + } elseif($limit === null && $offset !== null) { + $this->db->expects($this->at($this->prepareAt)) + ->method('prepare') + ->with($this->equalTo($sql), + $this->equalTo(null), + $this->equalTo($offset)) + ->will(($this->returnValue($this->query))); + } else { + $this->db->expects($this->at($this->prepareAt)) + ->method('prepare') + ->with($this->equalTo($sql), + $this->equalTo($limit), + $this->equalTo($offset)) + ->will(($this->returnValue($this->query))); + } $this->iterators[] = new ArgumentIterator($returnRows); $iterators = $this->iterators; $fetchAt = $this->fetchAt; - $this->pdoResult->expects($this->any()) + $this->query->expects($this->any()) ->method('fetch') ->will($this->returnCallback( function() use ($iterators, $fetchAt){ @@ -87,8 +111,10 @@ abstract class MapperTestUtility extends \Test\TestCase { $fetchAt++; } + $this->queryAt++; + return $result; - } + } )); $index = 1; @@ -105,7 +131,7 @@ abstract class MapperTestUtility extends \Test\TestCase { case 'boolean': $pdoConstant = \PDO::PARAM_BOOL; break; - + default: $pdoConstant = \PDO::PARAM_STR; break; @@ -121,38 +147,23 @@ abstract class MapperTestUtility extends \Test\TestCase { $this->query->expects($this->at($this->queryAt)) ->method('execute') - ->with() - ->will($this->returnValue($this->pdoResult)); + ->will($this->returnCallback(function($sql, $p=null, $o=null, $s=null) { + + })); $this->queryAt++; - if($limit === null && $offset === null) { - $this->db->expects($this->at($this->prepareAt)) - ->method('prepareQuery') - ->with($this->equalTo($sql)) - ->will(($this->returnValue($this->query))); - } elseif($limit !== null && $offset === null) { - $this->db->expects($this->at($this->prepareAt)) - ->method('prepareQuery') - ->with($this->equalTo($sql), $this->equalTo($limit)) - ->will(($this->returnValue($this->query))); - } elseif($limit === null && $offset !== null) { - $this->db->expects($this->at($this->prepareAt)) - ->method('prepareQuery') - ->with($this->equalTo($sql), - $this->equalTo(null), - $this->equalTo($offset)) - ->will(($this->returnValue($this->query))); - } else { - $this->db->expects($this->at($this->prepareAt)) - ->method('prepareQuery') - ->with($this->equalTo($sql), - $this->equalTo($limit), - $this->equalTo($offset)) - ->will(($this->returnValue($this->query))); + + + if ($expectClose) { + $closing = $this->at($this->queryAt); + } else { + $closing = $this->any(); } + $this->query->expects($closing)->method('closeCursor'); + $this->queryAt++; + $this->prepareAt++; $this->fetchAt++; - } @@ -162,11 +173,11 @@ abstract class MapperTestUtility extends \Test\TestCase { class ArgumentIterator { private $arguments; - + public function __construct($arguments){ $this->arguments = $arguments; } - + public function next(){ $result = array_shift($this->arguments); if($result === null){ diff --git a/tests/lib/appframework/dependencyinjection/DIContainerTest.php b/tests/lib/appframework/dependencyinjection/DIContainerTest.php index 08e72aff984..0cbdddbb205 100644 --- a/tests/lib/appframework/dependencyinjection/DIContainerTest.php +++ b/tests/lib/appframework/dependencyinjection/DIContainerTest.php @@ -71,7 +71,11 @@ class DIContainerTest extends \Test\TestCase { public function testMiddlewareDispatcherIncludesSecurityMiddleware(){ - $this->container['Request'] = new Request(array('method' => 'GET')); + $this->container['Request'] = new Request( + ['method' => 'GET'], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); $security = $this->container['SecurityMiddleware']; $dispatcher = $this->container['MiddlewareDispatcher']; diff --git a/tests/lib/appframework/http/ContentSecurityPolicyTest.php b/tests/lib/appframework/http/ContentSecurityPolicyTest.php new file mode 100644 index 00000000000..f79c23ae644 --- /dev/null +++ b/tests/lib/appframework/http/ContentSecurityPolicyTest.php @@ -0,0 +1,230 @@ +<?php +/** + * Copyright (c) 2015 Lukas Reschke lukas@owncloud.com + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + + +namespace OC\AppFramework\Http; + +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\ContentSecurityPolicy; + +/** + * Class ContentSecurityPolicyTest + * + * @package OC\AppFramework\Http + */ +class ContentSecurityPolicyTest extends \Test\TestCase { + + /** @var ContentSecurityPolicy */ + private $contentSecurityPolicy; + + public function setUp() { + parent::setUp(); + $this->contentSecurityPolicy = new ContentSecurityPolicy(); + } + + public function testGetPolicyDefault() { + $defaultPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; + $this->assertSame($defaultPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' www.owncloud.com 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' www.owncloud.com www.owncloud.org 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptAllowInline() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->allowInlineScript(true); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptAllowInlineWithDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' www.owncloud.com 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); + $this->contentSecurityPolicy->allowInlineScript(true); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyScriptDisallowInlineAndEval() { + $expectedPolicy = "default-src 'none';script-src 'self';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->allowInlineScript(false); + $this->contentSecurityPolicy->allowEvalScript(false); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com www.owncloud.org 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleAllowInline() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->allowInlineStyle(true); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleAllowInlineWithDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyStyleDisallowInline() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->allowInlineStyle(false); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyImageDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' www.owncloud.com;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyImageDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' www.owncloud.com www.owncloud.org;font-src 'self';connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyFontDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self' www.owncloud.com;connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyFontDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self' www.owncloud.com www.owncloud.org;connect-src 'self';media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyConnectDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self' www.owncloud.com;media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyConnectDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self' www.owncloud.com www.owncloud.org;media-src 'self'"; + + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyMediaDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self' www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyMediaDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self' www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyObjectDomainValid() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self';object-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyObjectDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self';object-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetAllowedFrameDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self';frame-src www.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyFrameDomainValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self';frame-src www.owncloud.com www.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); + $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetAllowedChildSrcDomain() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self';child-src child.owncloud.com"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.com'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testGetPolicyChildSrcValidMultiple() { + $expectedPolicy = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self';child-src child.owncloud.com child.owncloud.org"; + + $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.com'); + $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } + + public function testConfigureStacked() { + $expectedPolicy = "default-src 'none';script-src 'self' script.owncloud.org;style-src 'self' style.owncloud.org;img-src 'self' img.owncloud.org;font-src 'self' font.owncloud.org;connect-src 'self' connect.owncloud.org;media-src 'self' media.owncloud.org;object-src objects.owncloud.org;frame-src frame.owncloud.org;child-src child.owncloud.org"; + + $this->contentSecurityPolicy->allowInlineStyle(false) + ->allowEvalScript(false) + ->addAllowedScriptDomain('script.owncloud.org') + ->addAllowedStyleDomain('style.owncloud.org') + ->addAllowedFontDomain('font.owncloud.org') + ->addAllowedImageDomain('img.owncloud.org') + ->addAllowedConnectDomain('connect.owncloud.org') + ->addAllowedMediaDomain('media.owncloud.org') + ->addAllowedObjectDomain('objects.owncloud.org') + ->addAllowedChildSrcDomain('child.owncloud.org') + ->addAllowedFrameDomain('frame.owncloud.org'); + $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); + } +} diff --git a/tests/lib/appframework/http/DataResponseTest.php b/tests/lib/appframework/http/DataResponseTest.php index e91d3cefea9..ca0582e10e5 100644 --- a/tests/lib/appframework/http/DataResponseTest.php +++ b/tests/lib/appframework/http/DataResponseTest.php @@ -66,7 +66,10 @@ class DataResponseTest extends \Test\TestCase { $headers = array('test' => 'something'); $response = new DataResponse($data, $code, $headers); - $expectedHeaders = array('Cache-Control' => 'no-cache, must-revalidate'); + $expectedHeaders = [ + 'Cache-Control' => 'no-cache, must-revalidate', + 'Content-Security-Policy' => "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'", + ]; $expectedHeaders = array_merge($expectedHeaders, $headers); $this->assertEquals($data, $response->getData()); diff --git a/tests/lib/appframework/http/DispatcherTest.php b/tests/lib/appframework/http/DispatcherTest.php index 3933e00804b..02c86df8e72 100644 --- a/tests/lib/appframework/http/DispatcherTest.php +++ b/tests/lib/appframework/http/DispatcherTest.php @@ -24,7 +24,6 @@ namespace OC\AppFramework\Http; -use OC\AppFramework\Middleware\MiddlewareDispatcher; use OC\AppFramework\Utility\ControllerMethodReflector; use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; @@ -33,6 +32,10 @@ use OCP\AppFramework\Controller; class TestController extends Controller { + /** + * @param string $appName + * @param \OCP\IRequest $request + */ public function __construct($appName, $request) { parent::__construct($appName, $request); } @@ -40,6 +43,9 @@ class TestController extends Controller { /** * @param int $int * @param bool $bool + * @param int $test + * @param int $test2 + * @return array */ public function exec($int, $bool, $test=4, $test2=1) { $this->registerResponder('text', function($in) { @@ -52,6 +58,9 @@ class TestController extends Controller { /** * @param int $int * @param bool $bool + * @param int $test + * @param int $test2 + * @return DataResponse */ public function execDataResponse($int, $bool, $test=4, $test2=1) { return new DataResponse(array( @@ -67,6 +76,7 @@ class DispatcherTest extends \Test\TestCase { private $dispatcher; private $controllerMethod; private $response; + private $request; private $lastModified; private $etag; private $http; @@ -276,13 +286,17 @@ class DispatcherTest extends \Test\TestCase { public function testControllerParametersInjected() { - $this->request = new Request(array( - 'post' => array( + $this->request = new Request( + [ + 'post' => [ 'int' => '3', 'bool' => 'false' - ), - 'method' => 'POST' - )); + ], + 'method' => 'POST' + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); $this->dispatcher = new Dispatcher( $this->http, $this->middlewareDispatcher, $this->reflector, $this->request @@ -298,14 +312,18 @@ class DispatcherTest extends \Test\TestCase { public function testControllerParametersInjectedDefaultOverwritten() { - $this->request = new Request(array( - 'post' => array( - 'int' => '3', - 'bool' => 'false', - 'test2' => 7 - ), - 'method' => 'POST' - )); + $this->request = new Request( + [ + 'post' => [ + 'int' => '3', + 'bool' => 'false', + 'test2' => 7 + ], + 'method' => 'POST', + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); $this->dispatcher = new Dispatcher( $this->http, $this->middlewareDispatcher, $this->reflector, $this->request @@ -322,16 +340,20 @@ class DispatcherTest extends \Test\TestCase { public function testResponseTransformedByUrlFormat() { - $this->request = new Request(array( - 'post' => array( - 'int' => '3', - 'bool' => 'false' - ), - 'urlParams' => array( - 'format' => 'text' - ), - 'method' => 'GET' - )); + $this->request = new Request( + [ + 'post' => [ + 'int' => '3', + 'bool' => 'false' + ], + 'urlParams' => [ + 'format' => 'text' + ], + 'method' => 'GET' + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); $this->dispatcher = new Dispatcher( $this->http, $this->middlewareDispatcher, $this->reflector, $this->request @@ -347,16 +369,20 @@ class DispatcherTest extends \Test\TestCase { public function testResponseTransformsDataResponse() { - $this->request = new Request(array( - 'post' => array( - 'int' => '3', - 'bool' => 'false' - ), - 'urlParams' => array( - 'format' => 'json' - ), - 'method' => 'GET' - )); + $this->request = new Request( + [ + 'post' => [ + 'int' => '3', + 'bool' => 'false' + ], + 'urlParams' => [ + 'format' => 'json' + ], + 'method' => 'GET' + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); $this->dispatcher = new Dispatcher( $this->http, $this->middlewareDispatcher, $this->reflector, $this->request @@ -372,17 +398,21 @@ class DispatcherTest extends \Test\TestCase { public function testResponseTransformedByAcceptHeader() { - $this->request = new Request(array( - 'post' => array( - 'int' => '3', - 'bool' => 'false' - ), - 'server' => array( - 'HTTP_ACCEPT' => 'application/text, test', - 'HTTP_CONTENT_TYPE' => 'application/x-www-form-urlencoded' - ), - 'method' => 'PUT' - )); + $this->request = new Request( + [ + 'post' => [ + 'int' => '3', + 'bool' => 'false' + ], + 'server' => [ + 'HTTP_ACCEPT' => 'application/text, test', + 'HTTP_CONTENT_TYPE' => 'application/x-www-form-urlencoded' + ], + 'method' => 'PUT' + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); $this->dispatcher = new Dispatcher( $this->http, $this->middlewareDispatcher, $this->reflector, $this->request @@ -398,19 +428,23 @@ class DispatcherTest extends \Test\TestCase { public function testResponsePrimarilyTransformedByParameterFormat() { - $this->request = new Request(array( - 'post' => array( - 'int' => '3', - 'bool' => 'false' - ), - 'get' => array( - 'format' => 'text' - ), - 'server' => array( - 'HTTP_ACCEPT' => 'application/json, test' - ), - 'method' => 'POST' - )); + $this->request = new Request( + [ + 'post' => [ + 'int' => '3', + 'bool' => 'false' + ], + 'get' => [ + 'format' => 'text' + ], + 'server' => [ + 'HTTP_ACCEPT' => 'application/json, test' + ], + 'method' => 'POST' + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); $this->dispatcher = new Dispatcher( $this->http, $this->middlewareDispatcher, $this->reflector, $this->request diff --git a/tests/lib/appframework/http/OCSResponseTest.php b/tests/lib/appframework/http/OCSResponseTest.php new file mode 100644 index 00000000000..111dc7ad0a3 --- /dev/null +++ b/tests/lib/appframework/http/OCSResponseTest.php @@ -0,0 +1,73 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2015 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library 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 library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace OC\AppFramework\Http; + + +use OCP\AppFramework\Http\OCSResponse; + + +class OCSResponseTest extends \Test\TestCase { + + + public function testHeadersJSON() { + $response = new OCSResponse('json', 1, 2, 3); + $type = $response->getHeaders()['Content-Type']; + $this->assertEquals('application/json; charset=utf-8', $type); + } + + + public function testHeadersXML() { + $response = new OCSResponse('xml', 1, 2, 3); + $type = $response->getHeaders()['Content-Type']; + $this->assertEquals('application/xml; charset=utf-8', $type); + } + + + public function testRender() { + $response = new OCSResponse( + 'xml', 'status', 2, 'message', ['test' => 'hi'], 'tag', 'abc', + 'dynamic', 3, 4 + ); + $out = $response->render(); + $expected = "<?xml version=\"1.0\"?>\n" . + "<ocs>\n" . + " <meta>\n" . + " <status>status</status>\n" . + " <statuscode>2</statuscode>\n" . + " <message>message</message>\n" . + " <totalitems>3</totalitems>\n" . + " <itemsperpage>4</itemsperpage>\n" . + " </meta>\n" . + " <data>\n" . + " <test>hi</test>\n" . + " </data>\n" . + "</ocs>\n"; + + $this->assertEquals($expected, $out); + + } + + +} diff --git a/tests/lib/appframework/http/RequestTest.php b/tests/lib/appframework/http/RequestTest.php index 85db76efe71..282d13a3397 100644 --- a/tests/lib/appframework/http/RequestTest.php +++ b/tests/lib/appframework/http/RequestTest.php @@ -1,6 +1,8 @@ <?php /** - * Copyright (c) 2013 Thomas Tanghus (thomas@tanghus.net) + * @copyright 2013 Thomas Tanghus (thomas@tanghus.net) + * @copyright 2015 Lukas Reschke lukas@owncloud.com + * * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. @@ -8,9 +10,21 @@ namespace OC\AppFramework\Http; -global $data; +use OCP\Security\ISecureRandom; +use OCP\IConfig; +/** + * Class RequestTest + * + * @package OC\AppFramework\Http + */ class RequestTest extends \Test\TestCase { + /** @var string */ + protected $stream = 'fakeinput://data'; + /** @var ISecureRandom */ + protected $secureRandom; + /** @var IConfig */ + protected $config; protected function setUp() { parent::setUp(); @@ -20,7 +34,9 @@ class RequestTest extends \Test\TestCase { stream_wrapper_unregister('fakeinput'); } stream_wrapper_register('fakeinput', 'RequestStream'); - $this->stream = 'fakeinput://data'; + + $this->secureRandom = $this->getMockBuilder('\OCP\Security\ISecureRandom')->getMock(); + $this->config = $this->getMockBuilder('\OCP\IConfig')->getMock(); } protected function tearDown() { @@ -34,7 +50,12 @@ class RequestTest extends \Test\TestCase { 'method' => 'GET', ); - $request = new Request($vars, $this->stream); + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); // Countable $this->assertEquals(2, count($request)); @@ -61,7 +82,12 @@ class RequestTest extends \Test\TestCase { 'method' => 'GET' ); - $request = new Request($vars, $this->stream); + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); $this->assertEquals(3, count($request)); $this->assertEquals('Janey', $request->{'nickname'}); @@ -70,7 +96,7 @@ class RequestTest extends \Test\TestCase { /** - * @expectedException RuntimeException + * @expectedException \RuntimeException */ public function testImmutableArrayAccess() { $vars = array( @@ -78,12 +104,18 @@ class RequestTest extends \Test\TestCase { 'method' => 'GET' ); - $request = new Request($vars, $this->stream); + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); + $request['nickname'] = 'Janey'; } /** - * @expectedException RuntimeException + * @expectedException \RuntimeException */ public function testImmutableMagicAccess() { $vars = array( @@ -91,12 +123,18 @@ class RequestTest extends \Test\TestCase { 'method' => 'GET' ); - $request = new Request($vars, $this->stream); + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); + $request->{'nickname'} = 'Janey'; } /** - * @expectedException LogicException + * @expectedException \LogicException */ public function testGetTheMethodRight() { $vars = array( @@ -104,8 +142,14 @@ class RequestTest extends \Test\TestCase { 'method' => 'GET', ); - $request = new Request($vars, $this->stream); - $result = $request->post; + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); + + $request->post; } public function testTheMethodIsRight() { @@ -114,7 +158,13 @@ class RequestTest extends \Test\TestCase { 'method' => 'GET', ); - $request = new Request($vars, $this->stream); + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); + $this->assertEquals('GET', $request->method); $result = $request->get; $this->assertEquals('John Q. Public', $result['name']); @@ -129,7 +179,13 @@ class RequestTest extends \Test\TestCase { 'server' => array('CONTENT_TYPE' => 'application/json; utf-8') ); - $request = new Request($vars, $this->stream); + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); + $this->assertEquals('POST', $request->method); $result = $request->post; $this->assertEquals('John Q. Public', $result['name']); @@ -147,7 +203,12 @@ class RequestTest extends \Test\TestCase { 'server' => array('CONTENT_TYPE' => 'application/x-www-form-urlencoded'), ); - $request = new Request($vars, $this->stream); + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); $this->assertEquals('PATCH', $request->method); $result = $request->patch; @@ -166,7 +227,12 @@ class RequestTest extends \Test\TestCase { 'server' => array('CONTENT_TYPE' => 'application/json; utf-8'), ); - $request = new Request($vars, $this->stream); + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); $this->assertEquals('PUT', $request->method); $result = $request->put; @@ -181,7 +247,12 @@ class RequestTest extends \Test\TestCase { 'server' => array('CONTENT_TYPE' => 'application/json; utf-8'), ); - $request = new Request($vars, $this->stream); + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); $this->assertEquals('PATCH', $request->method); $result = $request->patch; @@ -200,7 +271,13 @@ class RequestTest extends \Test\TestCase { 'server' => array('CONTENT_TYPE' => 'image/png'), ); - $request = new Request($vars, $this->stream); + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); + $this->assertEquals('PUT', $request->method); $resource = $request->put; $contents = stream_get_contents($resource); @@ -223,7 +300,12 @@ class RequestTest extends \Test\TestCase { 'urlParams' => array('id' => '2'), ); - $request = new Request($vars, $this->stream); + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); $newParams = array('id' => '3', 'test' => 'test2'); $request->setUrlParameters($newParams); @@ -231,4 +313,747 @@ class RequestTest extends \Test\TestCase { $this->assertEquals('3', $request->getParam('id')); $this->assertEquals('3', $request->getParams()['id']); } + + public function testGetIdWithModUnique() { + $vars = [ + 'server' => [ + 'UNIQUE_ID' => 'GeneratedUniqueIdByModUnique' + ], + ]; + + $request = new Request( + $vars, + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertSame('GeneratedUniqueIdByModUnique', $request->getId()); + } + + public function testGetIdWithoutModUnique() { + $lowRandomSource = $this->getMockBuilder('\OCP\Security\ISecureRandom') + ->disableOriginalConstructor()->getMock(); + $lowRandomSource->expects($this->once()) + ->method('generate') + ->with('20') + ->will($this->returnValue('GeneratedByOwnCloudItself')); + + $this->secureRandom + ->expects($this->once()) + ->method('getLowStrengthGenerator') + ->will($this->returnValue($lowRandomSource)); + + $request = new Request( + [], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertSame('GeneratedByOwnCloudItself', $request->getId()); + } + + public function testGetIdWithoutModUniqueStable() { + $request = new Request( + [], + \OC::$server->getSecureRandom(), + $this->config, + $this->stream + ); + $firstId = $request->getId(); + $secondId = $request->getId(); + $this->assertSame($firstId, $secondId); + } + + public function testGetRemoteAddressWithoutTrustedRemote() { + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('trusted_proxies') + ->will($this->returnValue([])); + + $request = new Request( + [ + 'server' => [ + 'REMOTE_ADDR' => '10.0.0.2', + 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4', + 'HTTP_X_FORWARDED_FOR' => '192.168.0.233' + ], + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertSame('10.0.0.2', $request->getRemoteAddress()); + } + + public function testGetRemoteAddressWithNoTrustedHeader() { + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('trusted_proxies') + ->will($this->returnValue(['10.0.0.2'])); + $this->config + ->expects($this->at(1)) + ->method('getSystemValue') + ->with('forwarded_for_headers') + ->will($this->returnValue([])); + + $request = new Request( + [ + 'server' => [ + 'REMOTE_ADDR' => '10.0.0.2', + 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4', + 'HTTP_X_FORWARDED_FOR' => '192.168.0.233' + ], + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertSame('10.0.0.2', $request->getRemoteAddress()); + } + + public function testGetRemoteAddressWithSingleTrustedRemote() { + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('trusted_proxies') + ->will($this->returnValue(['10.0.0.2'])); + $this->config + ->expects($this->at(1)) + ->method('getSystemValue') + ->with('forwarded_for_headers') + ->will($this->returnValue(['HTTP_X_FORWARDED'])); + + $request = new Request( + [ + 'server' => [ + 'REMOTE_ADDR' => '10.0.0.2', + 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4', + 'HTTP_X_FORWARDED_FOR' => '192.168.0.233' + ], + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertSame('10.4.0.5', $request->getRemoteAddress()); + } + + public function testGetRemoteAddressVerifyPriorityHeader() { + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('trusted_proxies') + ->will($this->returnValue(['10.0.0.2'])); + $this->config + ->expects($this->at(1)) + ->method('getSystemValue') + ->with('forwarded_for_headers') + ->will($this->returnValue([ + 'HTTP_CLIENT_IP', + 'HTTP_X_FORWARDED_FOR', + 'HTTP_X_FORWARDED' + ])); + + $request = new Request( + [ + 'server' => [ + 'REMOTE_ADDR' => '10.0.0.2', + 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4', + 'HTTP_X_FORWARDED_FOR' => '192.168.0.233' + ], + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertSame('192.168.0.233', $request->getRemoteAddress()); + } + + public function testGetServerProtocolWithOverride() { + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('overwriteprotocol') + ->will($this->returnValue('customProtocol')); + $this->config + ->expects($this->at(1)) + ->method('getSystemValue') + ->with('overwritecondaddr') + ->will($this->returnValue('')); + $this->config + ->expects($this->at(2)) + ->method('getSystemValue') + ->with('overwriteprotocol') + ->will($this->returnValue('customProtocol')); + + $request = new Request( + [], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertSame('customProtocol', $request->getServerProtocol()); + } + + public function testGetServerProtocolWithProtoValid() { + $this->config + ->expects($this->exactly(2)) + ->method('getSystemValue') + ->with('overwriteprotocol') + ->will($this->returnValue('')); + + $requestHttps = new Request( + [ + 'server' => [ + 'HTTP_X_FORWARDED_PROTO' => 'HtTpS' + ], + ], + $this->secureRandom, + $this->config, + $this->stream + ); + $requestHttp = new Request( + [ + 'server' => [ + 'HTTP_X_FORWARDED_PROTO' => 'HTTp' + ], + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + + $this->assertSame('https', $requestHttps->getServerProtocol()); + $this->assertSame('http', $requestHttp->getServerProtocol()); + } + + public function testGetServerProtocolWithHttpsServerValueOn() { + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('overwriteprotocol') + ->will($this->returnValue('')); + + $request = new Request( + [ + 'server' => [ + 'HTTPS' => 'on' + ], + ], + $this->secureRandom, + $this->config, + $this->stream + ); + $this->assertSame('https', $request->getServerProtocol()); + } + + public function testGetServerProtocolWithHttpsServerValueOff() { + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('overwriteprotocol') + ->will($this->returnValue('')); + + $request = new Request( + [ + 'server' => [ + 'HTTPS' => 'off' + ], + ], + $this->secureRandom, + $this->config, + $this->stream + ); + $this->assertSame('http', $request->getServerProtocol()); + } + + public function testGetServerProtocolDefault() { + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('overwriteprotocol') + ->will($this->returnValue('')); + + $request = new Request( + [], + $this->secureRandom, + $this->config, + $this->stream + ); + $this->assertSame('http', $request->getServerProtocol()); + } + + public function testGetServerProtocolBehindLoadBalancers() { + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('overwriteprotocol') + ->will($this->returnValue('')); + + $request = new Request( + [ + 'server' => [ + 'HTTP_X_FORWARDED_PROTO' => 'https,http,http' + ], + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertSame('https', $request->getServerProtocol()); + } + + /** + * @dataProvider userAgentProvider + * @param string $testAgent + * @param array $userAgent + * @param bool $matches + */ + public function testUserAgent($testAgent, $userAgent, $matches) { + $request = new Request( + [ + 'server' => [ + 'HTTP_USER_AGENT' => $testAgent, + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertEquals($matches, $request->isUserAgent($userAgent)); + } + + /** + * @return array + */ + function userAgentProvider() { + return [ + [ + 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', + [ + Request::USER_AGENT_IE + ], + true, + ], + [ + 'Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0', + [ + Request::USER_AGENT_IE + ], + false, + ], + [ + 'Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36', + [ + Request::USER_AGENT_ANDROID_MOBILE_CHROME + ], + true, + ], + [ + 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', + [ + Request::USER_AGENT_ANDROID_MOBILE_CHROME + ], + false, + ], + [ + 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', + [ + Request::USER_AGENT_IE, + Request::USER_AGENT_ANDROID_MOBILE_CHROME, + ], + true, + ], + [ + 'Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36', + [ + Request::USER_AGENT_IE, + Request::USER_AGENT_ANDROID_MOBILE_CHROME, + ], + true, + ], + [ + 'Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0', + [ + Request::USER_AGENT_FREEBOX + ], + false, + ], + [ + 'Mozilla/5.0', + [ + Request::USER_AGENT_FREEBOX + ], + true, + ], + [ + 'Fake Mozilla/5.0', + [ + Request::USER_AGENT_FREEBOX + ], + false, + ], + ]; + } + + public function testInsecureServerHostServerNameHeader() { + $request = new Request( + [ + 'server' => [ + 'SERVER_NAME' => 'from.server.name:8080', + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertEquals('from.server.name:8080', $request->getInsecureServerHost()); + } + + public function testInsecureServerHostHttpHostHeader() { + $request = new Request( + [ + 'server' => [ + 'SERVER_NAME' => 'from.server.name:8080', + 'HTTP_HOST' => 'from.host.header:8080', + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertEquals('from.host.header:8080', $request->getInsecureServerHost()); + } + + public function testInsecureServerHostHttpFromForwardedHeaderSingle() { + $request = new Request( + [ + 'server' => [ + 'SERVER_NAME' => 'from.server.name:8080', + 'HTTP_HOST' => 'from.host.header:8080', + 'HTTP_X_FORWARDED_HOST' => 'from.forwarded.host:8080', + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertEquals('from.forwarded.host:8080', $request->getInsecureServerHost()); + } + + public function testInsecureServerHostHttpFromForwardedHeaderStacked() { + $request = new Request( + [ + 'server' => [ + 'SERVER_NAME' => 'from.server.name:8080', + 'HTTP_HOST' => 'from.host.header:8080', + 'HTTP_X_FORWARDED_HOST' => 'from.forwarded.host2:8080,another.one:9000', + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertEquals('from.forwarded.host2:8080', $request->getInsecureServerHost()); + } + + public function testGetServerHost() { + $request = new Request( + [], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertEquals('localhost', $request->getServerHost()); + } + + public function testGetOverwriteHostDefaultNull() { + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('overwritehost') + ->will($this->returnValue('')); + $request = new Request( + [], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertNull(\Test_Helper::invokePrivate($request, 'getOverwriteHost')); + } + + public function testGetOverwriteHostWithOverwrite() { + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('overwritehost') + ->will($this->returnValue('www.owncloud.org')); + $this->config + ->expects($this->at(1)) + ->method('getSystemValue') + ->with('overwritecondaddr') + ->will($this->returnValue('')); + $this->config + ->expects($this->at(2)) + ->method('getSystemValue') + ->with('overwritehost') + ->will($this->returnValue('www.owncloud.org')); + + $request = new Request( + [], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertSame('www.owncloud.org', \Test_Helper::invokePrivate($request, 'getOverwriteHost')); + } + + public function testGetPathInfoWithSetEnv() { + $request = new Request( + [ + 'server' => [ + 'PATH_INFO' => 'apps/files/', + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertEquals('apps/files/', $request->getPathInfo()); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage The requested uri(/foo.php) cannot be processed by the script '/var/www/index.php') + */ + public function testGetPathInfoNotProcessible() { + $request = new Request( + [ + 'server' => [ + 'REQUEST_URI' => '/foo.php', + 'SCRIPT_NAME' => '/var/www/index.php', + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $request->getPathInfo(); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage The requested uri(/foo.php) cannot be processed by the script '/var/www/index.php') + */ + public function testGetRawPathInfoNotProcessible() { + $request = new Request( + [ + 'server' => [ + 'REQUEST_URI' => '/foo.php', + 'SCRIPT_NAME' => '/var/www/index.php', + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $request->getRawPathInfo(); + } + + /** + * @dataProvider genericPathInfoProvider + * @param string $requestUri + * @param string $scriptName + * @param string $expected + */ + public function testGetPathInfoWithoutSetEnvGeneric($requestUri, $scriptName, $expected) { + $request = new Request( + [ + 'server' => [ + 'REQUEST_URI' => $requestUri, + 'SCRIPT_NAME' => $scriptName, + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertEquals($expected, $request->getPathInfo()); + } + + /** + * @dataProvider genericPathInfoProvider + * @param string $requestUri + * @param string $scriptName + * @param string $expected + */ + public function testGetRawPathInfoWithoutSetEnvGeneric($requestUri, $scriptName, $expected) { + $request = new Request( + [ + 'server' => [ + 'REQUEST_URI' => $requestUri, + 'SCRIPT_NAME' => $scriptName, + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertEquals($expected, $request->getRawPathInfo()); + } + + /** + * @dataProvider rawPathInfoProvider + * @param string $requestUri + * @param string $scriptName + * @param string $expected + */ + public function testGetRawPathInfoWithoutSetEnv($requestUri, $scriptName, $expected) { + $request = new Request( + [ + 'server' => [ + 'REQUEST_URI' => $requestUri, + 'SCRIPT_NAME' => $scriptName, + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertEquals($expected, $request->getRawPathInfo()); + } + + /** + * @dataProvider pathInfoProvider + * @param string $requestUri + * @param string $scriptName + * @param string $expected + */ + public function testGetPathInfoWithoutSetEnv($requestUri, $scriptName, $expected) { + $request = new Request( + [ + 'server' => [ + 'REQUEST_URI' => $requestUri, + 'SCRIPT_NAME' => $scriptName, + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertEquals($expected, $request->getPathInfo()); + } + + /** + * @return array + */ + public function genericPathInfoProvider() { + return [ + ['/index.php/apps/files/', 'index.php', '/apps/files/'], + ['/index.php/apps/files/../&/&?someQueryParameter=QueryParam', 'index.php', '/apps/files/../&/&'], + ['/remote.php/漢字編碼方法 / 汉字编码方法', 'remote.php', '/漢字編碼方法 / 汉字编码方法'], + ['///removeTrailin//gSlashes///', 'remote.php', '/removeTrailin/gSlashes/'], + ['/', '/', ''], + ['', '', ''], + ]; + } + + /** + * @return array + */ + public function rawPathInfoProvider() { + return [ + ['/foo%2Fbar/subfolder', '', 'foo%2Fbar/subfolder'], + ]; + } + + /** + * @return array + */ + public function pathInfoProvider() { + return [ + ['/foo%2Fbar/subfolder', '', 'foo/bar/subfolder'], + ]; + } + + public function testGetRequestUriWithoutOverwrite() { + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('overwritewebroot') + ->will($this->returnValue('')); + + $request = new Request( + [ + 'server' => [ + 'REQUEST_URI' => '/test.php' + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ); + + $this->assertSame('/test.php', $request->getRequestUri()); + } + + public function testGetRequestUriWithOverwrite() { + $this->config + ->expects($this->at(0)) + ->method('getSystemValue') + ->with('overwritewebroot') + ->will($this->returnValue('/owncloud/')); + $this->config + ->expects($this->at(1)) + ->method('getSystemValue') + ->with('overwritecondaddr') + ->will($this->returnValue('')); + + $request = $this->getMockBuilder('\OC\AppFramework\Http\Request') + ->setMethods(['getScriptName']) + ->setConstructorArgs([ + [ + 'server' => [ + 'REQUEST_URI' => '/test.php/some/PathInfo', + 'SCRIPT_NAME' => '/test.php', + ] + ], + $this->secureRandom, + $this->config, + $this->stream + ]) + ->getMock(); + $request + ->expects($this->once()) + ->method('getScriptName') + ->will($this->returnValue('/scriptname.php')); + + $this->assertSame('/scriptname.php/some/PathInfo', $request->getRequestUri()); + } } diff --git a/tests/lib/appframework/http/ResponseTest.php b/tests/lib/appframework/http/ResponseTest.php index b4352348bae..77e9441b52c 100644 --- a/tests/lib/appframework/http/ResponseTest.php +++ b/tests/lib/appframework/http/ResponseTest.php @@ -49,7 +49,7 @@ class ResponseTest extends \Test\TestCase { } - function testSetHeaders(){ + public function testSetHeaders() { $expected = array( 'Last-Modified' => 1, 'ETag' => 3, @@ -58,15 +58,40 @@ class ResponseTest extends \Test\TestCase { $this->childResponse->setHeaders($expected); $headers = $this->childResponse->getHeaders(); + $expected['Content-Security-Policy'] = "default-src 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'"; $this->assertEquals($expected, $headers); } + public function testOverwriteCsp() { + $expected = [ + 'Content-Security-Policy' => "default-src 'none';script-src 'self' 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'", + ]; + $policy = new Http\ContentSecurityPolicy(); + $policy->allowInlineScript(true); + + $this->childResponse->setContentSecurityPolicy($policy); + $headers = $this->childResponse->getHeaders(); + + $this->assertEquals(array_merge($expected, $headers), $headers); + } + + public function testGetCsp() { + $policy = new Http\ContentSecurityPolicy(); + $policy->allowInlineScript(true); + + $this->childResponse->setContentSecurityPolicy($policy); + $this->assertEquals($policy, $this->childResponse->getContentSecurityPolicy()); + } + + public function testGetCspEmpty() { + $this->assertNull($this->childResponse->getContentSecurityPolicy()); + } public function testAddHeaderValueNullDeletesIt(){ $this->childResponse->addHeader('hello', 'world'); $this->childResponse->addHeader('hello', null); - $this->assertEquals(1, count($this->childResponse->getHeaders())); + $this->assertEquals(2, count($this->childResponse->getHeaders())); } diff --git a/tests/lib/appframework/http/StreamResponseTest.php b/tests/lib/appframework/http/StreamResponseTest.php new file mode 100644 index 00000000000..4c47ecfbd6c --- /dev/null +++ b/tests/lib/appframework/http/StreamResponseTest.php @@ -0,0 +1,99 @@ +<?php + +/** + * ownCloud - App Framework + * + * @author Bernhard Posselt + * @copyright 2015 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library 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 library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace OC\AppFramework\Http; + + +use OCP\AppFramework\Http\StreamResponse; +use OCP\AppFramework\Http; + + +class StreamResponseTest extends \Test\TestCase { + + /** @var IOutput */ + private $output; + + protected function setUp() { + parent::setUp(); + $this->output = $this->getMock('OCP\\AppFramework\\Http\\IOutput'); + } + + public function testOutputNotModified(){ + $path = __FILE__; + $this->output->expects($this->once()) + ->method('getHttpResponseCode') + ->will($this->returnValue(Http::STATUS_NOT_MODIFIED)); + $this->output->expects($this->never()) + ->method('setReadfile'); + $response = new StreamResponse($path); + + $response->callback($this->output); + } + + public function testOutputOk(){ + $path = __FILE__; + $this->output->expects($this->once()) + ->method('getHttpResponseCode') + ->will($this->returnValue(Http::STATUS_OK)); + $this->output->expects($this->once()) + ->method('setReadfile') + ->with($this->equalTo($path)) + ->will($this->returnValue(true)); + $response = new StreamResponse($path); + + $response->callback($this->output); + } + + public function testOutputNotFound(){ + $path = __FILE__ . 'test'; + $this->output->expects($this->once()) + ->method('getHttpResponseCode') + ->will($this->returnValue(Http::STATUS_OK)); + $this->output->expects($this->never()) + ->method('setReadfile'); + $this->output->expects($this->once()) + ->method('setHttpResponseCode') + ->with($this->equalTo(Http::STATUS_NOT_FOUND)); + $response = new StreamResponse($path); + + $response->callback($this->output); + } + + public function testOutputReadFileError(){ + $path = __FILE__; + $this->output->expects($this->once()) + ->method('getHttpResponseCode') + ->will($this->returnValue(Http::STATUS_OK)); + $this->output->expects($this->once()) + ->method('setReadfile') + ->will($this->returnValue(false)); + $this->output->expects($this->once()) + ->method('setHttpResponseCode') + ->with($this->equalTo(Http::STATUS_BAD_REQUEST)); + $response = new StreamResponse($path); + + $response->callback($this->output); + } + +} diff --git a/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php b/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php index be8765afd39..a8731525798 100644 --- a/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php +++ b/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php @@ -126,8 +126,17 @@ class MiddlewareDispatcherTest extends \Test\TestCase { private function getControllerMock(){ - return $this->getMock('OCP\AppFramework\Controller', array('method'), - array('app', new Request(array('method' => 'GET')))); + return $this->getMock( + 'OCP\AppFramework\Controller', + ['method'], + ['app', + new Request( + ['method' => 'GET'], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ) + ] + ); } diff --git a/tests/lib/appframework/middleware/MiddlewareTest.php b/tests/lib/appframework/middleware/MiddlewareTest.php index b41ec33eb15..33f04e1383d 100644 --- a/tests/lib/appframework/middleware/MiddlewareTest.php +++ b/tests/lib/appframework/middleware/MiddlewareTest.php @@ -26,7 +26,7 @@ namespace OC\AppFramework; use OC\AppFramework\Http\Request; use OCP\AppFramework\Middleware; - +use OCP\AppFramework\Http\Response; class ChildMiddleware extends Middleware {}; @@ -40,6 +40,8 @@ class MiddlewareTest extends \Test\TestCase { private $controller; private $exception; private $api; + /** @var Response */ + private $response; protected function setUp(){ parent::setUp(); @@ -51,8 +53,18 @@ class MiddlewareTest extends \Test\TestCase { ->disableOriginalConstructor() ->getMock(); - $this->controller = $this->getMock('OCP\AppFramework\Controller', - array(), array($this->api, new Request())); + $this->controller = $this->getMock( + 'OCP\AppFramework\Controller', + [], + [ + $this->api, + new Request( + [], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ) + ] + ); $this->exception = new \Exception(); $this->response = $this->getMock('OCP\AppFramework\Http\Response'); } diff --git a/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php b/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php index b4bbcce5ad7..a4f3137cb11 100644 --- a/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php +++ b/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php @@ -32,7 +32,13 @@ class CORSMiddlewareTest extends \Test\TestCase { */ public function testSetCORSAPIHeader() { $request = new Request( - array('server' => array('HTTP_ORIGIN' => 'test')) + [ + 'server' => [ + 'HTTP_ORIGIN' => 'test' + ] + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') ); $this->reflector->reflect($this, __FUNCTION__); $middleware = new CORSMiddleware($request, $this->reflector); @@ -45,7 +51,13 @@ class CORSMiddlewareTest extends \Test\TestCase { public function testNoAnnotationNoCORSHEADER() { $request = new Request( - array('server' => array('HTTP_ORIGIN' => 'test')) + [ + 'server' => [ + 'HTTP_ORIGIN' => 'test' + ] + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') ); $middleware = new CORSMiddleware($request, $this->reflector); @@ -59,7 +71,11 @@ class CORSMiddlewareTest extends \Test\TestCase { * @CORS */ public function testNoOriginHeaderNoCORSHEADER() { - $request = new Request(); + $request = new Request( + [], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') + ); $this->reflector->reflect($this, __FUNCTION__); $middleware = new CORSMiddleware($request, $this->reflector); @@ -75,14 +91,20 @@ class CORSMiddlewareTest extends \Test\TestCase { */ public function testCorsIgnoredIfWithCredentialsHeaderPresent() { $request = new Request( - array('server' => array('HTTP_ORIGIN' => 'test')) + [ + 'server' => [ + 'HTTP_ORIGIN' => 'test' + ] + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') ); $this->reflector->reflect($this, __FUNCTION__); $middleware = new CORSMiddleware($request, $this->reflector); $response = new Response(); $response->addHeader('AcCess-control-Allow-Credentials ', 'TRUE'); - $response = $middleware->afterController($this, __FUNCTION__, $response); + $middleware->afterController($this, __FUNCTION__, $response); } } diff --git a/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php b/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php index a8925403a95..347a0423ea6 100644 --- a/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php +++ b/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php @@ -314,10 +314,15 @@ class SecurityMiddlewareTest extends \Test\TestCase { public function testAfterExceptionReturnsRedirect(){ $this->request = new Request( - array('server' => - array('HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', - 'REQUEST_URI' => 'owncloud/index.php/apps/specialapp') - ) + [ + 'server' => + [ + 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'REQUEST_URI' => 'owncloud/index.php/apps/specialapp' + ] + ], + $this->getMock('\OCP\Security\ISecureRandom'), + $this->getMock('\OCP\IConfig') ); $this->middleware = $this->getMiddleware(true, true); $response = $this->middleware->afterException($this->controller, 'test', diff --git a/tests/lib/appframework/middleware/sessionmiddlewaretest.php b/tests/lib/appframework/middleware/sessionmiddlewaretest.php index 344b555ec3c..11c1600f515 100644 --- a/tests/lib/appframework/middleware/sessionmiddlewaretest.php +++ b/tests/lib/appframework/middleware/sessionmiddlewaretest.php @@ -33,7 +33,11 @@ class SessionMiddlewareTest extends \Test\TestCase { protected function setUp() { parent::setUp(); - $this->request = new Request(); + $this->request = new Request( + [], + $this->getMockBuilder('\OCP\Security\ISecureRandom')->getMock(), + $this->getMock('\OCP\IConfig') + ); $this->reflector = new ControllerMethodReflector(); } diff --git a/tests/lib/appframework/utility/ControllerMethodReflectorTest.php b/tests/lib/appframework/utility/ControllerMethodReflectorTest.php index cd6bd57da4c..c513e23cd6b 100644 --- a/tests/lib/appframework/utility/ControllerMethodReflectorTest.php +++ b/tests/lib/appframework/utility/ControllerMethodReflectorTest.php @@ -25,6 +25,38 @@ namespace OC\AppFramework\Utility; +class BaseController { + + /** + * @Annotation + */ + public function test(){} + + /** + * @Annotation + */ + public function test2(){} + + /** + * @Annotation + */ + public function test3(){} + +} + +class MiddleController extends BaseController { + + /** + * @NoAnnotation + */ + public function test2() {} + + public function test3() {} + +} + +class EndController extends MiddleController {} + class ControllerMethodReflectorTest extends \Test\TestCase { @@ -96,7 +128,7 @@ class ControllerMethodReflectorTest extends \Test\TestCase { 'arguments' ); - $this->assertEquals(array('arg' => null, 'arg2' => 'hi'), $reader->getParameters()); + $this->assertEquals(array('arg' => null, 'arg2' => 'hi'), $reader->getParameters()); } @@ -108,8 +140,32 @@ class ControllerMethodReflectorTest extends \Test\TestCase { 'arguments2' ); - $this->assertEquals(array('arg' => null), $reader->getParameters()); + $this->assertEquals(array('arg' => null), $reader->getParameters()); + } + + + public function testInheritance() { + $reader = new ControllerMethodReflector(); + $reader->reflect('OC\AppFramework\Utility\EndController', 'test'); + + $this->assertTrue($reader->hasAnnotation('Annotation')); } + public function testInheritanceOverride() { + $reader = new ControllerMethodReflector(); + $reader->reflect('OC\AppFramework\Utility\EndController', 'test2'); + + $this->assertTrue($reader->hasAnnotation('NoAnnotation')); + $this->assertFalse($reader->hasAnnotation('Annotation')); + } + + + public function testInheritanceOverrideNoDocblock() { + $reader = new ControllerMethodReflector(); + $reader->reflect('OC\AppFramework\Utility\EndController', 'test3'); + + $this->assertFalse($reader->hasAnnotation('Annotation')); + } + } diff --git a/tests/lib/backgroundjob/dummyjoblist.php b/tests/lib/backgroundjob/dummyjoblist.php index 7801269b27e..6cc690fd553 100644 --- a/tests/lib/backgroundjob/dummyjoblist.php +++ b/tests/lib/backgroundjob/dummyjoblist.php @@ -21,13 +21,18 @@ class DummyJobList extends \OC\BackgroundJob\JobList { private $last = 0; - public function __construct(){} + public function __construct() { + } /** * @param \OC\BackgroundJob\Job|string $job * @param mixed $argument */ public function add($job, $argument = null) { + if (is_string($job)) { + /** @var \OC\BackgroundJob\Job $job */ + $job = new $job; + } $job->setArgument($argument); if (!$this->has($job, null)) { $this->jobs[] = $job; diff --git a/tests/lib/cache/fileglobalgc.php b/tests/lib/cache/fileglobalgc.php new file mode 100644 index 00000000000..0b0a4cb002d --- /dev/null +++ b/tests/lib/cache/fileglobalgc.php @@ -0,0 +1,73 @@ +<?php +/** + * ownCloud + * + * @author Robin Appelman + * @copyright 2012 Robin Appelman icewind@owncloud.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library 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 library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace Test\Cache; + +use Test\TestCase; + +class FileGlobalGC extends TestCase { + /** + * @var string + */ + private $cacheDir; + + /** + * @var \OC\Cache\FileGlobalGC + */ + private $gc; + + public function setUp() { + $this->cacheDir = \OC::$server->getTempManager()->getTemporaryFolder(); + $this->gc = new \OC\Cache\FileGlobalGC(); + } + + private function addCacheFile($name, $expire) { + file_put_contents($this->cacheDir . $name, 'foo'); + touch($this->cacheDir . $name, $expire); + } + + public function testGetExpiredEmpty() { + $this->assertEquals([], $this->gc->getExpiredPaths($this->cacheDir, time())); + } + + public function testGetExpiredNone() { + $time = time(); + $this->addCacheFile('foo', $time + 10); + $this->assertEquals([], $this->gc->getExpiredPaths($this->cacheDir, $time)); + } + + public function testGetExpired() { + $time = time(); + $this->addCacheFile('foo', $time + 10); + $this->addCacheFile('bar', $time); + $this->addCacheFile('bar2', $time - 10); + $this->addCacheFile('asd', $time - 100); + $this->assertEquals([$this->cacheDir . 'asd', $this->cacheDir . 'bar2'], $this->gc->getExpiredPaths($this->cacheDir, $time)); + } + + public function testGetExpiredDirectory() { + $time = time(); + $this->addCacheFile('foo', $time - 10); + mkdir($this->cacheDir . 'asd'); + $this->assertEquals([$this->cacheDir . 'foo'], $this->gc->getExpiredPaths($this->cacheDir, $time)); + } +} diff --git a/tests/lib/command/asyncbus.php b/tests/lib/command/asyncbus.php new file mode 100644 index 00000000000..183eaa29c37 --- /dev/null +++ b/tests/lib/command/asyncbus.php @@ -0,0 +1,179 @@ +<?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\Command; + +use OC\Command\FileAccess; +use OCP\Command\IBus; +use OCP\Command\ICommand; +use Test\BackgroundJob\DummyJobList; +use Test\TestCase; + +class SimpleCommand implements ICommand { + public function handle() { + AsyncBus::$lastCommand = 'SimpleCommand'; + } +} + +class StateFullCommand implements ICommand { + private $state; + + function __construct($state) { + $this->state = $state; + } + + public function handle() { + AsyncBus::$lastCommand = $this->state; + } +} + +class FilesystemCommand implements ICommand { + use FileAccess; + + public function handle() { + AsyncBus::$lastCommand = 'FileAccess'; + } +} + +function basicFunction() { + AsyncBus::$lastCommand = 'function'; +} + +// clean class to prevent phpunit putting closure in $this +class ThisClosureTest { + private function privateMethod() { + AsyncBus::$lastCommand = 'closure-this'; + } + + public function test(IBus $bus) { + $bus->push(function () { + $this->privateMethod(); + }); + } +} + +class AsyncBus extends TestCase { + /** + * Basic way to check output from a command + * + * @var string + */ + public static $lastCommand; + + /** + * @var \OCP\BackgroundJob\IJobList + */ + private $jobList; + + /** + * @var \OCP\Command\IBus + */ + private $bus; + + public static function DummyCommand() { + self::$lastCommand = 'static'; + } + + public function setUp() { + $this->jobList = new DummyJobList(); + $this->bus = new \OC\Command\AsyncBus($this->jobList); + self::$lastCommand = ''; + } + + public function testSimpleCommand() { + $command = new SimpleCommand(); + $this->bus->push($command); + $this->runJobs(); + $this->assertEquals('SimpleCommand', self::$lastCommand); + } + + public function testStateFullCommand() { + $command = new StateFullCommand('foo'); + $this->bus->push($command); + $this->runJobs(); + $this->assertEquals('foo', self::$lastCommand); + } + + public function testStaticCallable() { + $this->bus->push(['\Test\Command\AsyncBus', 'DummyCommand']); + $this->runJobs(); + $this->assertEquals('static', self::$lastCommand); + } + + public function testMemberCallable() { + $command = new StateFullCommand('bar'); + $this->bus->push([$command, 'handle']); + $this->runJobs(); + $this->assertEquals('bar', self::$lastCommand); + } + + public function testFunctionCallable() { + $this->bus->push('\Test\Command\BasicFunction'); + $this->runJobs(); + $this->assertEquals('function', self::$lastCommand); + } + + public function testClosure() { + $this->bus->push(function () { + AsyncBus::$lastCommand = 'closure'; + }); + $this->runJobs(); + $this->assertEquals('closure', self::$lastCommand); + } + + public function testClosureSelf() { + $this->bus->push(function () { + self::$lastCommand = 'closure-self'; + }); + $this->runJobs(); + $this->assertEquals('closure-self', self::$lastCommand); + } + + + public function testClosureThis() { + // clean class to prevent phpunit putting closure in $this + $test = new ThisClosureTest(); + $test->test($this->bus); + $this->runJobs(); + $this->assertEquals('closure-this', self::$lastCommand); + } + + public function testClosureBind() { + $state = 'bar'; + $this->bus->push(function () use ($state) { + self::$lastCommand = 'closure-' . $state; + }); + $this->runJobs(); + $this->assertEquals('closure-bar', self::$lastCommand); + } + + public function testFileFileAccessCommand() { + $this->bus->push(new FilesystemCommand()); + $this->assertEquals('', self::$lastCommand); + $this->runJobs(); + $this->assertEquals('FileAccess', self::$lastCommand); + } + + public function testFileFileAccessCommandSync() { + $this->bus->requireSync('\OC\Command\FileAccess'); + $this->bus->push(new FilesystemCommand()); + $this->assertEquals('FileAccess', self::$lastCommand); + self::$lastCommand = ''; + $this->runJobs(); + $this->assertEquals('', self::$lastCommand); + } + + + private function runJobs() { + $jobs = $this->jobList->getAll(); + foreach ($jobs as $job) { + $job->execute($this->jobList); + } + } +} diff --git a/tests/lib/command/background.php b/tests/lib/command/background.php new file mode 100644 index 00000000000..7e992480530 --- /dev/null +++ b/tests/lib/command/background.php @@ -0,0 +1,58 @@ +<?php +/** +* The MIT License (MIT) +* +* Copyright (c) 2015 Christian Kampka <christian@kampka.net> +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +namespace Test\Command; + +use Test\TestCase; +use Symfony\Component\Console\Input\StringInput; +use Symfony\Component\Console\Output\NullOutput; + +use OC\Core\Command\Background\Cron; +use OC\Core\Command\Background\WebCron; +use OC\Core\Command\Background\Ajax; + +class BackgroundJobs extends TestCase { + + public function testCronCommand() { + $config = \OC::$server->getConfig(); + $job = new Cron($config); + $job->run(new StringInput(''), new NullOutput()); + $this->assertEquals('cron', $config->getAppValue('core', 'backgroundjobs_mode')); + } + + public function testAjaxCommand() { + $config = \OC::$server->getConfig(); + $job = new Ajax($config); + $job->run(new StringInput(''), new NullOutput()); + $this->assertEquals('ajax', $config->getAppValue('core', 'backgroundjobs_mode')); + } + + public function testWebCronCommand() { + $config = \OC::$server->getConfig(); + $job = new WebCron($config); + $job->run(new StringInput(''), new NullOutput()); + $this->assertEquals('webcron', $config->getAppValue('core', 'backgroundjobs_mode')); + } +} diff --git a/tests/lib/connector/sabre/custompropertiesbackend.php b/tests/lib/connector/sabre/custompropertiesbackend.php new file mode 100644 index 00000000000..ee0c3c4e53d --- /dev/null +++ b/tests/lib/connector/sabre/custompropertiesbackend.php @@ -0,0 +1,248 @@ +<?php + +namespace Tests\Connector\Sabre; + +/** + * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +class CustomPropertiesBackend extends \Test\TestCase { + + /** + * @var \Sabre\DAV\Server + */ + private $server; + + /** + * @var \Sabre\DAV\ObjectTree + */ + private $tree; + + /** + * @var \OC\Connector\Sabre\CustomPropertiesBackend + */ + private $plugin; + + /** + * @var \OCP\IUser + */ + private $user; + + public function setUp() { + parent::setUp(); + $this->server = new \Sabre\DAV\Server(); + $this->tree = $this->getMockBuilder('\Sabre\DAV\Tree') + ->disableOriginalConstructor() + ->getMock(); + + $userId = $this->getUniqueID('testcustompropertiesuser'); + + $this->user = $this->getMock('\OCP\IUser'); + $this->user->expects($this->any()) + ->method('getUID') + ->will($this->returnValue($userId)); + + $this->plugin = new \OC\Connector\Sabre\CustomPropertiesBackend( + $this->tree, + \OC::$server->getDatabaseConnection(), + $this->user + ); + } + + public function tearDown() { + $connection = \OC::$server->getDatabaseConnection(); + $deleteStatement = $connection->prepare( + 'DELETE FROM `*PREFIX*properties`' . + ' WHERE `userid` = ?' + ); + $deleteStatement->execute( + array( + $this->user->getUID(), + ) + ); + $deleteStatement->closeCursor(); + } + + private function createTestNode($class) { + $node = $this->getMockBuilder($class) + ->disableOriginalConstructor() + ->getMock(); + $node->expects($this->any()) + ->method('getId') + ->will($this->returnValue(123)); + + $node->expects($this->any()) + ->method('getPath') + ->will($this->returnValue('/dummypath')); + + return $node; + } + + private function applyDefaultProps($path = '/dummypath') { + // properties to set + $propPatch = new \Sabre\DAV\PropPatch(array( + 'customprop' => 'value1', + 'customprop2' => 'value2', + )); + + $this->plugin->propPatch( + $path, + $propPatch + ); + + $propPatch->commit(); + + $this->assertEmpty($propPatch->getRemainingMutations()); + + $result = $propPatch->getResult(); + $this->assertEquals(200, $result['customprop']); + $this->assertEquals(200, $result['customprop2']); + } + + /** + * Test setting/getting properties + */ + public function testSetGetPropertiesForFile() { + $node = $this->createTestNode('\OC\Connector\Sabre\File'); + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/dummypath') + ->will($this->returnValue($node)); + + $this->applyDefaultProps(); + + $propFind = new \Sabre\DAV\PropFind( + '/dummypath', + array( + 'customprop', + 'customprop2', + 'unsetprop', + ), + 0 + ); + + $this->plugin->propFind( + '/dummypath', + $propFind + ); + + $this->assertEquals('value1', $propFind->get('customprop')); + $this->assertEquals('value2', $propFind->get('customprop2')); + $this->assertEquals(array('unsetprop'), $propFind->get404Properties()); + } + + /** + * Test getting properties from directory + */ + public function testGetPropertiesForDirectory() { + $rootNode = $this->createTestNode('\OC\Connector\Sabre\Directory'); + + $nodeSub = $this->getMockBuilder('\OC\Connector\Sabre\File') + ->disableOriginalConstructor() + ->getMock(); + $nodeSub->expects($this->any()) + ->method('getId') + ->will($this->returnValue(456)); + + $nodeSub->expects($this->any()) + ->method('getPath') + ->will($this->returnValue('/dummypath/test.txt')); + + $rootNode->expects($this->once()) + ->method('getChildren') + ->will($this->returnValue(array($nodeSub))); + + $this->tree->expects($this->at(0)) + ->method('getNodeForPath') + ->with('/dummypath') + ->will($this->returnValue($rootNode)); + + $this->tree->expects($this->at(1)) + ->method('getNodeForPath') + ->with('/dummypath/test.txt') + ->will($this->returnValue($nodeSub)); + + $this->tree->expects($this->at(2)) + ->method('getNodeForPath') + ->with('/dummypath') + ->will($this->returnValue($rootNode)); + + $this->tree->expects($this->at(3)) + ->method('getNodeForPath') + ->with('/dummypath/test.txt') + ->will($this->returnValue($nodeSub)); + + $this->applyDefaultProps('/dummypath'); + $this->applyDefaultProps('/dummypath/test.txt'); + + $propNames = array( + 'customprop', + 'customprop2', + 'unsetprop', + ); + + $propFindRoot = new \Sabre\DAV\PropFind( + '/dummypath', + $propNames, + 1 + ); + + $propFindSub = new \Sabre\DAV\PropFind( + '/dummypath/test.txt', + $propNames, + 0 + ); + + $this->plugin->propFind( + '/dummypath', + $propFindRoot + ); + + $this->plugin->propFind( + '/dummypath/test.txt', + $propFindSub + ); + + // TODO: find a way to assert that no additional SQL queries were + // run while doing the second propFind + + $this->assertEquals('value1', $propFindRoot->get('customprop')); + $this->assertEquals('value2', $propFindRoot->get('customprop2')); + $this->assertEquals(array('unsetprop'), $propFindRoot->get404Properties()); + + $this->assertEquals('value1', $propFindSub->get('customprop')); + $this->assertEquals('value2', $propFindSub->get('customprop2')); + $this->assertEquals(array('unsetprop'), $propFindSub->get404Properties()); + } + + /** + * Test delete property + */ + public function testDeleteProperty() { + $node = $this->createTestNode('\OC\Connector\Sabre\File'); + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/dummypath') + ->will($this->returnValue($node)); + + $this->applyDefaultProps(); + + $propPatch = new \Sabre\DAV\PropPatch(array( + 'customprop' => null, + )); + + $this->plugin->propPatch( + '/dummypath', + $propPatch + ); + + $propPatch->commit(); + + $this->assertEmpty($propPatch->getRemainingMutations()); + + $result = $propPatch->getResult(); + $this->assertEquals(204, $result['customprop']); + } +} diff --git a/tests/lib/connector/sabre/directory.php b/tests/lib/connector/sabre/directory.php index e9bfea81b77..2550f2bcef1 100644 --- a/tests/lib/connector/sabre/directory.php +++ b/tests/lib/connector/sabre/directory.php @@ -8,7 +8,9 @@ */ class Test_OC_Connector_Sabre_Directory extends \Test\TestCase { + /** @var OC\Files\View | PHPUnit_Framework_MockObject_MockObject */ private $view; + /** @var OC\Files\FileInfo | PHPUnit_Framework_MockObject_MockObject */ private $info; protected function setUp() { @@ -27,7 +29,7 @@ class Test_OC_Connector_Sabre_Directory extends \Test\TestCase { ->method('getPath') ->will($this->returnValue('')); - return new OC_Connector_Sabre_Directory($this->view, $this->info); + return new \OC\Connector\Sabre\Directory($this->view, $this->info); } /** @@ -131,7 +133,7 @@ class Test_OC_Connector_Sabre_Directory extends \Test\TestCase { ->method('getRelativePath') ->will($this->returnValue('')); - $dir = new OC_Connector_Sabre_Directory($this->view, $this->info); + $dir = new \OC\Connector\Sabre\Directory($this->view, $this->info); $nodes = $dir->getChildren(); $this->assertEquals(2, count($nodes)); @@ -139,20 +141,35 @@ class Test_OC_Connector_Sabre_Directory extends \Test\TestCase { // calling a second time just returns the cached values, // does not call getDirectoryContents again $nodes = $dir->getChildren(); + } - $properties = array('testprop', OC_Connector_Sabre_Node::GETETAG_PROPERTYNAME); - $this->assertEquals(2, count($nodes)); - $this->assertEquals( - array( - OC_Connector_Sabre_Node::GETETAG_PROPERTYNAME => '"abc"' - ), - $nodes[0]->getProperties($properties) - ); - $this->assertEquals( - array( - OC_Connector_Sabre_Node::GETETAG_PROPERTYNAME => '"def"' - ), - $nodes[1]->getProperties($properties) - ); + public function testGetQuotaInfo() { + $storage = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Quota') + ->disableOriginalConstructor() + ->getMock(); + + $storage->expects($this->once()) + ->method('instanceOfStorage') + ->with('\OC\Files\Storage\Wrapper\Quota') + ->will($this->returnValue(true)); + + $storage->expects($this->once()) + ->method('getQuota') + ->will($this->returnValue(1000)); + + $storage->expects($this->once()) + ->method('free_space') + ->will($this->returnValue(800)); + + $this->info->expects($this->once()) + ->method('getSize') + ->will($this->returnValue(200)); + + $this->info->expects($this->once()) + ->method('getStorage') + ->will($this->returnValue($storage)); + + $dir = new \OC\Connector\Sabre\Directory($this->view, $this->info); + $this->assertEquals([200, 800], $dir->getQuotaInfo()); //200 used, 800 free } } diff --git a/tests/lib/connector/sabre/exception/invalidpathtest.php b/tests/lib/connector/sabre/exception/invalidpathtest.php new file mode 100644 index 00000000000..d2d58887d62 --- /dev/null +++ b/tests/lib/connector/sabre/exception/invalidpathtest.php @@ -0,0 +1,44 @@ +<?php + +namespace Test\Connector\Sabre\Exception; + +use OC\Connector\Sabre\Exception\InvalidPath; + +/** + * Copyright (c) 2015 Thomas Müller <deepdiver@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +class InvalidPathTest extends \Test\TestCase { + + public function testSerialization() { + + // create xml doc + $DOM = new \DOMDocument('1.0','utf-8'); + $DOM->formatOutput = true; + $error = $DOM->createElementNS('DAV:','d:error'); + $error->setAttribute('xmlns:s', \Sabre\DAV\Server::NS_SABREDAV); + $DOM->appendChild($error); + + // serialize the exception + $message = "1234567890"; + $retry = false; + $expectedXml = <<<EOD +<?xml version="1.0" encoding="utf-8"?> +<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:o="http://owncloud.org/ns"> + <o:retry xmlns:o="o:">false</o:retry> + <o:reason xmlns:o="o:">1234567890</o:reason> +</d:error> + +EOD; + + $ex = new InvalidPath($message, $retry); + $server = $this->getMock('Sabre\DAV\Server'); + $ex->serialize($server, $error); + + // assert + $xml = $DOM->saveXML(); + $this->assertEquals($expectedXml, $xml); + } +} diff --git a/tests/lib/connector/sabre/exceptionloggerplugin.php b/tests/lib/connector/sabre/exceptionloggerplugin.php new file mode 100644 index 00000000000..0662ba029d9 --- /dev/null +++ b/tests/lib/connector/sabre/exceptionloggerplugin.php @@ -0,0 +1,71 @@ +<?php + +/** + * Copyright (c) 2015 Thomas Müller <deepdiver@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; + +use OC\Connector\Sabre\Exception\InvalidPath; +use OC\Connector\Sabre\ExceptionLoggerPlugin as PluginToTest; +use OC\Log; +use OCP\ILogger; +use PHPUnit_Framework_MockObject_MockObject; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\Server; +use Test\TestCase; + +class TestLogger extends Log { + public $message; + public $level; + + public function __construct($logger = null) { + //disable original constructor + } + + public function log($level, $message, array $context = array()) { + $this->level = $level; + $this->message = $message; + } +} + +class ExceptionLoggerPlugin extends TestCase { + + /** @var Server */ + private $server; + + /** @var PluginToTest */ + private $plugin; + + /** @var TestLogger | PHPUnit_Framework_MockObject_MockObject */ + private $logger; + + private function init() { + $this->server = new Server(); + $this->logger = new TestLogger(); + $this->plugin = new PluginToTest('unit-test', $this->logger); + $this->plugin->initialize($this->server); + } + + /** + * @dataProvider providesExceptions + */ + public function testLogging($expectedLogLevel, $expectedMessage, $exception) { + $this->init(); + $this->plugin->logException($exception); + + $this->assertEquals($expectedLogLevel, $this->logger->level); + $this->assertStringStartsWith('Exception: {"Message":"' . $expectedMessage, $this->logger->message); + } + + public function providesExceptions() { + return [ + [0, 'HTTP\/1.1 404 Not Found', new NotFound()], + [4, 'HTTP\/1.1 400 This path leads to nowhere', new InvalidPath('This path leads to nowhere')] + ]; + } + +} diff --git a/tests/lib/connector/sabre/file.php b/tests/lib/connector/sabre/file.php index 33dc78f87d8..74e289c1751 100644 --- a/tests/lib/connector/sabre/file.php +++ b/tests/lib/connector/sabre/file.php @@ -6,7 +6,9 @@ * See the COPYING-README file. */ -class Test_OC_Connector_Sabre_File extends \Test\TestCase { +namespace Test\Connector\Sabre; + +class File extends \Test\TestCase { /** * @expectedException \Sabre\DAV\Exception @@ -26,7 +28,7 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase { 'permissions'=>\OCP\Constants::PERMISSION_ALL ), null); - $file = new OC_Connector_Sabre_File($view, $info); + $file = new \OC\Connector\Sabre\File($view, $info); // action $file->put('test data'); @@ -52,7 +54,7 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase { 'permissions' => \OCP\Constants::PERMISSION_ALL ), null); - $file = new OC_Connector_Sabre_File($view, $info); + $file = new \OC\Connector\Sabre\File($view, $info); $this->assertNotEmpty($file->put('test data')); } @@ -86,14 +88,14 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase { 'permissions' => \OCP\Constants::PERMISSION_ALL ), null); - $file = new OC_Connector_Sabre_File($view, $info); + $file = new \OC\Connector\Sabre\File($view, $info); // action $file->put('test data'); } /** - * @expectedException \Sabre\DAV\Exception\BadRequest + * @expectedException \OC\Connector\Sabre\Exception\InvalidPath */ public function testSimplePutInvalidChars() { // setup @@ -104,12 +106,12 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase { $view->expects($this->any()) ->method('getRelativePath') - ->will($this->returnValue('/super*star.txt')); + ->will($this->returnValue('/*')); - $info = new \OC\Files\FileInfo('/super*star.txt', null, null, array( + $info = new \OC\Files\FileInfo('/*', null, null, array( 'permissions' => \OCP\Constants::PERMISSION_ALL ), null); - $file = new OC_Connector_Sabre_File($view, $info); + $file = new \OC\Connector\Sabre\File($view, $info); // action $file->put('test data'); @@ -117,7 +119,7 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase { /** * Test setting name with setName() with invalid chars - * @expectedException \Sabre\DAV\Exception\BadRequest + * @expectedException \OC\Connector\Sabre\Exception\InvalidPath */ public function testSetNameInvalidChars() { // setup @@ -125,12 +127,12 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase { $view->expects($this->any()) ->method('getRelativePath') - ->will($this->returnValue('/super*star.txt')); + ->will($this->returnValue('/*')); - $info = new \OC\Files\FileInfo('/super*star.txt', null, null, array( + $info = new \OC\Files\FileInfo('/*', null, null, array( 'permissions' => \OCP\Constants::PERMISSION_ALL ), null); - $file = new OC_Connector_Sabre_File($view, $info); + $file = new \OC\Connector\Sabre\File($view, $info); $file->setName('/super*star.txt'); } @@ -163,7 +165,7 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase { 'permissions' => \OCP\Constants::PERMISSION_ALL ), null); - $file = new OC_Connector_Sabre_File($view, $info); + $file = new \OC\Connector\Sabre\File($view, $info); // action $file->put('test data'); @@ -185,7 +187,7 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase { 'permissions' => \OCP\Constants::PERMISSION_ALL ), null); - $file = new OC_Connector_Sabre_File($view, $info); + $file = new \OC\Connector\Sabre\File($view, $info); // action $file->delete(); @@ -203,7 +205,7 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase { 'permissions' => 0 ), null); - $file = new OC_Connector_Sabre_File($view, $info); + $file = new \OC\Connector\Sabre\File($view, $info); // action $file->delete(); @@ -226,7 +228,7 @@ class Test_OC_Connector_Sabre_File extends \Test\TestCase { 'permissions' => \OCP\Constants::PERMISSION_ALL ), null); - $file = new OC_Connector_Sabre_File($view, $info); + $file = new \OC\Connector\Sabre\File($view, $info); // action $file->delete(); diff --git a/tests/lib/connector/sabre/filesplugin.php b/tests/lib/connector/sabre/filesplugin.php new file mode 100644 index 00000000000..54d43d66dda --- /dev/null +++ b/tests/lib/connector/sabre/filesplugin.php @@ -0,0 +1,174 @@ +<?php + +namespace Tests\Connector\Sabre; + +/** + * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +class FilesPlugin extends \Test\TestCase { + const GETETAG_PROPERTYNAME = \OC\Connector\Sabre\FilesPlugin::GETETAG_PROPERTYNAME; + const FILEID_PROPERTYNAME = \OC\Connector\Sabre\FilesPlugin::FILEID_PROPERTYNAME; + const SIZE_PROPERTYNAME = \OC\Connector\Sabre\FilesPlugin::SIZE_PROPERTYNAME; + const PERMISSIONS_PROPERTYNAME = \OC\Connector\Sabre\FilesPlugin::PERMISSIONS_PROPERTYNAME; + const GETLASTMODIFIED_PROPERTYNAME = \OC\Connector\Sabre\FilesPlugin::GETLASTMODIFIED_PROPERTYNAME; + const DOWNLOADURL_PROPERTYNAME = \OC\Connector\Sabre\FilesPlugin::DOWNLOADURL_PROPERTYNAME; + + /** + * @var \Sabre\DAV\Server + */ + private $server; + + /** + * @var \Sabre\DAV\ObjectTree + */ + private $tree; + + /** + * @var \OC\Connector\Sabre\FilesPlugin + */ + private $plugin; + + public function setUp() { + parent::setUp(); + $this->server = new \Sabre\DAV\Server(); + $this->tree = $this->getMockBuilder('\Sabre\DAV\Tree') + ->disableOriginalConstructor() + ->getMock(); + $this->plugin = new \OC\Connector\Sabre\FilesPlugin($this->tree); + $this->plugin->initialize($this->server); + } + + private function createTestNode($class) { + $node = $this->getMockBuilder($class) + ->disableOriginalConstructor() + ->getMock(); + $node->expects($this->any()) + ->method('getId') + ->will($this->returnValue(123)); + + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/dummypath') + ->will($this->returnValue($node)); + + $node->expects($this->any()) + ->method('getFileId') + ->will($this->returnValue(123)); + $node->expects($this->any()) + ->method('getEtag') + ->will($this->returnValue('"abc"')); + $node->expects($this->any()) + ->method('getDavPermissions') + ->will($this->returnValue('R')); + + return $node; + } + + /** + */ + public function testGetPropertiesForFile() { + $node = $this->createTestNode('\OC\Connector\Sabre\File'); + + $propFind = new \Sabre\DAV\PropFind( + '/dummyPath', + array( + self::GETETAG_PROPERTYNAME, + self::FILEID_PROPERTYNAME, + self::SIZE_PROPERTYNAME, + self::PERMISSIONS_PROPERTYNAME, + self::DOWNLOADURL_PROPERTYNAME, + ), + 0 + ); + + $node->expects($this->once()) + ->method('getDirectDownload') + ->will($this->returnValue(array('url' => 'http://example.com/'))); + $node->expects($this->never()) + ->method('getSize'); + + $this->plugin->handleGetProperties( + $propFind, + $node + ); + + $this->assertEquals('"abc"', $propFind->get(self::GETETAG_PROPERTYNAME)); + $this->assertEquals(123, $propFind->get(self::FILEID_PROPERTYNAME)); + $this->assertEquals(null, $propFind->get(self::SIZE_PROPERTYNAME)); + $this->assertEquals('R', $propFind->get(self::PERMISSIONS_PROPERTYNAME)); + $this->assertEquals('http://example.com/', $propFind->get(self::DOWNLOADURL_PROPERTYNAME)); + $this->assertEquals(array(self::SIZE_PROPERTYNAME), $propFind->get404Properties()); + } + + public function testGetPropertiesForDirectory() { + $node = $this->createTestNode('\OC\Connector\Sabre\Directory'); + + $propFind = new \Sabre\DAV\PropFind( + '/dummyPath', + array( + self::GETETAG_PROPERTYNAME, + self::FILEID_PROPERTYNAME, + self::SIZE_PROPERTYNAME, + self::PERMISSIONS_PROPERTYNAME, + self::DOWNLOADURL_PROPERTYNAME, + ), + 0 + ); + + $node->expects($this->never()) + ->method('getDirectDownload'); + $node->expects($this->once()) + ->method('getSize') + ->will($this->returnValue(1025)); + + $this->plugin->handleGetProperties( + $propFind, + $node + ); + + $this->assertEquals('"abc"', $propFind->get(self::GETETAG_PROPERTYNAME)); + $this->assertEquals(123, $propFind->get(self::FILEID_PROPERTYNAME)); + $this->assertEquals(1025, $propFind->get(self::SIZE_PROPERTYNAME)); + $this->assertEquals('R', $propFind->get(self::PERMISSIONS_PROPERTYNAME)); + $this->assertEquals(null, $propFind->get(self::DOWNLOADURL_PROPERTYNAME)); + $this->assertEquals(array(self::DOWNLOADURL_PROPERTYNAME), $propFind->get404Properties()); + } + + public function testUpdateProps() { + $node = $this->createTestNode('\OC\Connector\Sabre\File'); + + $testDate = 'Fri, 13 Feb 2015 00:01:02 GMT'; + + $node->expects($this->once()) + ->method('touch') + ->with($testDate); + + $node->expects($this->once()) + ->method('setEtag') + ->with('newetag') + ->will($this->returnValue(true)); + + // properties to set + $propPatch = new \Sabre\DAV\PropPatch(array( + self::GETETAG_PROPERTYNAME => 'newetag', + self::GETLASTMODIFIED_PROPERTYNAME => $testDate + )); + + $this->plugin->handleUpdateProperties( + '/dummypath', + $propPatch + ); + + $propPatch->commit(); + + $this->assertEmpty($propPatch->getRemainingMutations()); + + $result = $propPatch->getResult(); + $this->assertEquals(200, $result[self::GETLASTMODIFIED_PROPERTYNAME]); + $this->assertEquals(200, $result[self::GETETAG_PROPERTYNAME]); + } + +} diff --git a/tests/lib/connector/sabre/node.php b/tests/lib/connector/sabre/node.php index 1e927deed44..3b3a6107813 100644 --- a/tests/lib/connector/sabre/node.php +++ b/tests/lib/connector/sabre/node.php @@ -9,9 +9,6 @@ namespace Test\Connector\Sabre; -use OC\Files\FileInfo; -use OC\Files\View; - class Node extends \Test\TestCase { public function davPermissionsProvider() { return array( @@ -49,7 +46,7 @@ class Node extends \Test\TestCase { ->will($this->returnValue($type)); $view = $this->getMock('\OC\Files\View'); - $node = new \OC_Connector_Sabre_File($view, $info); + $node = new \OC\Connector\Sabre\File($view, $info); $this->assertEquals($expected, $node->getDavPermissions()); } } diff --git a/tests/lib/connector/sabre/objecttree.php b/tests/lib/connector/sabre/objecttree.php index 2548066214b..d2702027b0d 100644 --- a/tests/lib/connector/sabre/objecttree.php +++ b/tests/lib/connector/sabre/objecttree.php @@ -10,8 +10,7 @@ namespace Test\OC\Connector\Sabre; use OC\Files\FileInfo; -use OC_Connector_Sabre_Directory; -use PHPUnit_Framework_TestCase; +use OC\Connector\Sabre\Directory; class TestDoubleFileView extends \OC\Files\View { @@ -48,29 +47,29 @@ class ObjectTree extends \Test\TestCase { * @dataProvider moveFailedProvider * @expectedException \Sabre\DAV\Exception\Forbidden */ - public function testMoveFailed($source, $dest, $updatables, $deletables) { - $this->moveTest($source, $dest, $updatables, $deletables); + public function testMoveFailed($source, $destination, $updatables, $deletables) { + $this->moveTest($source, $destination, $updatables, $deletables); } /** * @dataProvider moveSuccessProvider */ - public function testMoveSuccess($source, $dest, $updatables, $deletables) { - $this->moveTest($source, $dest, $updatables, $deletables); + public function testMoveSuccess($source, $destination, $updatables, $deletables) { + $this->moveTest($source, $destination, $updatables, $deletables); $this->assertTrue(true); } /** * @dataProvider moveFailedInvalidCharsProvider - * @expectedException \Sabre\DAV\Exception\BadRequest + * @expectedException \OC\Connector\Sabre\Exception\InvalidPath */ - public function testMoveFailedInvalidChars($source, $dest, $updatables, $deletables) { - $this->moveTest($source, $dest, $updatables, $deletables); + public function testMoveFailedInvalidChars($source, $destination, $updatables, $deletables) { + $this->moveTest($source, $destination, $updatables, $deletables); } function moveFailedInvalidCharsProvider() { return array( - array('a/b', 'a/c*', array('a' => false, 'a/b' => true, 'a/c*' => false), array()), + array('a/b', 'a/*', array('a' => false, 'a/b' => true, 'a/c*' => false), array()), ); } @@ -95,15 +94,15 @@ class ObjectTree extends \Test\TestCase { /** * @param $source - * @param $dest + * @param $destination * @param $updatables */ - private function moveTest($source, $dest, $updatables, $deletables) { + private function moveTest($source, $destination, $updatables, $deletables) { $view = new TestDoubleFileView($updatables, $deletables); $info = new FileInfo('', null, null, array(), null); - $rootDir = new OC_Connector_Sabre_Directory($view, $info); + $rootDir = new Directory($view, $info); $objectTree = $this->getMock('\OC\Connector\Sabre\ObjectTree', array('nodeExists', 'getNodeForPath'), array($rootDir, $view)); @@ -116,7 +115,126 @@ class ObjectTree extends \Test\TestCase { /** @var $objectTree \OC\Connector\Sabre\ObjectTree */ $mountManager = \OC\Files\Filesystem::getMountManager(); $objectTree->init($rootDir, $view, $mountManager); - $objectTree->move($source, $dest); + $objectTree->move($source, $destination); + } + + /** + * @dataProvider nodeForPathProvider + */ + public function testGetNodeForPath( + $inputFileName, + $fileInfoQueryPath, + $outputFileName, + $type, + $enableChunkingHeader + ) { + + if ($enableChunkingHeader) { + $_SERVER['HTTP_OC_CHUNKED'] = true; + } + + $rootNode = $this->getMockBuilder('\OC\Connector\Sabre\Directory') + ->disableOriginalConstructor() + ->getMock(); + $mountManager = $this->getMock('\OC\Files\Mount\Manager'); + $view = $this->getMock('\OC\Files\View'); + $fileInfo = $this->getMock('\OCP\Files\FileInfo'); + $fileInfo->expects($this->once()) + ->method('getType') + ->will($this->returnValue($type)); + $fileInfo->expects($this->once()) + ->method('getName') + ->will($this->returnValue($outputFileName)); + + $view->expects($this->once()) + ->method('getFileInfo') + ->with($fileInfoQueryPath) + ->will($this->returnValue($fileInfo)); + + $tree = new \OC\Connector\Sabre\ObjectTree(); + $tree->init($rootNode, $view, $mountManager); + + $node = $tree->getNodeForPath($inputFileName); + + $this->assertNotNull($node); + $this->assertEquals($outputFileName, $node->getName()); + + if ($type === 'file') { + $this->assertTrue($node instanceof \OC\Connector\Sabre\File); + } else { + $this->assertTrue($node instanceof \OC\Connector\Sabre\Directory); + } + + unset($_SERVER['HTTP_OC_CHUNKED']); + } + + function nodeForPathProvider() { + return array( + // regular file + array( + 'regularfile.txt', + 'regularfile.txt', + 'regularfile.txt', + 'file', + false + ), + // regular directory + array( + 'regulardir', + 'regulardir', + 'regulardir', + 'dir', + false + ), + // regular file with chunking + array( + 'regularfile.txt', + 'regularfile.txt', + 'regularfile.txt', + 'file', + true + ), + // regular directory with chunking + array( + 'regulardir', + 'regulardir', + 'regulardir', + 'dir', + true + ), + // file with chunky file name + array( + 'regularfile.txt-chunking-123566789-10-1', + 'regularfile.txt', + 'regularfile.txt', + 'file', + true + ), + // regular file in subdir + array( + 'subdir/regularfile.txt', + 'subdir/regularfile.txt', + 'regularfile.txt', + 'file', + false + ), + // regular directory in subdir + array( + 'subdir/regulardir', + 'subdir/regulardir', + 'regulardir', + 'dir', + false + ), + // file with chunky file name in subdir + array( + 'subdir/regularfile.txt-chunking-123566789-10-1', + 'subdir/regularfile.txt', + 'regularfile.txt', + 'file', + true + ), + ); } } diff --git a/tests/lib/connector/sabre/principal.php b/tests/lib/connector/sabre/principal.php index 5d13aa4421e..1841a79bec7 100644 --- a/tests/lib/connector/sabre/principal.php +++ b/tests/lib/connector/sabre/principal.php @@ -10,6 +10,7 @@ namespace Test\Connector\Sabre; +use \Sabre\DAV\PropPatch; use OCP\IUserManager; use OCP\IConfig; @@ -240,7 +241,7 @@ class Principal extends \Test\TestCase { } public function testUpdatePrincipal() { - $this->assertSame(0, $this->connector->updatePrincipal('foo', [])); + $this->assertSame(0, $this->connector->updatePrincipal('foo', new PropPatch(array()))); } public function testSearchPrincipals() { diff --git a/tests/lib/connector/sabre/quotaplugin.php b/tests/lib/connector/sabre/quotaplugin.php index f08637854ce..48f8f319ae4 100644 --- a/tests/lib/connector/sabre/quotaplugin.php +++ b/tests/lib/connector/sabre/quotaplugin.php @@ -14,14 +14,14 @@ class Test_OC_Connector_Sabre_QuotaPlugin extends \Test\TestCase { private $server; /** - * @var OC_Connector_Sabre_QuotaPlugin + * @var \OC\Connector\Sabre\QuotaPlugin */ private $plugin; private function init($quota) { $view = $this->buildFileViewMock($quota); $this->server = new \Sabre\DAV\Server(); - $this->plugin = new OC_Connector_Sabre_QuotaPlugin($view); + $this->plugin = new \OC\Connector\Sabre\QuotaPlugin($view); $this->plugin->initialize($this->server); } @@ -30,7 +30,7 @@ class Test_OC_Connector_Sabre_QuotaPlugin extends \Test\TestCase { */ public function testLength($expected, $headers) { $this->init(0); - $this->server->httpRequest = new \Sabre\HTTP\Request($headers); + $this->server->httpRequest = new \Sabre\HTTP\Request(null, null, $headers); $length = $this->plugin->getLength(); $this->assertEquals($expected, $length); } @@ -41,7 +41,7 @@ class Test_OC_Connector_Sabre_QuotaPlugin extends \Test\TestCase { public function testCheckQuota($quota, $headers) { $this->init($quota); - $this->server->httpRequest = new Sabre\HTTP\Request($headers); + $this->server->httpRequest = new \Sabre\HTTP\Request(null, null, $headers); $result = $this->plugin->checkQuota(''); $this->assertTrue($result); } @@ -53,39 +53,39 @@ class Test_OC_Connector_Sabre_QuotaPlugin extends \Test\TestCase { public function testCheckExceededQuota($quota, $headers) { $this->init($quota); - $this->server->httpRequest = new Sabre\HTTP\Request($headers); + $this->server->httpRequest = new \Sabre\HTTP\Request(null, null, $headers); $this->plugin->checkQuota(''); } public function quotaOkayProvider() { return array( array(1024, array()), - array(1024, array('HTTP_X_EXPECTED_ENTITY_LENGTH' => '1024')), - array(1024, array('HTTP_CONTENT_LENGTH' => '512')), - array(1024, array('HTTP_OC_TOTAL_LENGTH' => '1024', 'HTTP_CONTENT_LENGTH' => '512')), - // \OCP\Files\FileInfo::SPACE_UNKNOWN = -2 + array(1024, array('X-EXPECTED-ENTITY-LENGTH' => '1024')), + array(1024, array('CONTENT-LENGTH' => '512')), + array(1024, array('OC-TOTAL-LENGTH' => '1024', 'CONTENT-LENGTH' => '512')), + // \OCP\Files\FileInfo::SPACE-UNKNOWN = -2 array(-2, array()), - array(-2, array('HTTP_X_EXPECTED_ENTITY_LENGTH' => '1024')), - array(-2, array('HTTP_CONTENT_LENGTH' => '512')), - array(-2, array('HTTP_OC_TOTAL_LENGTH' => '1024', 'HTTP_CONTENT_LENGTH' => '512')), + array(-2, array('X-EXPECTED-ENTITY-LENGTH' => '1024')), + array(-2, array('CONTENT-LENGTH' => '512')), + array(-2, array('OC-TOTAL-LENGTH' => '1024', 'CONTENT-LENGTH' => '512')), ); } public function quotaExceededProvider() { return array( - array(1023, array('HTTP_X_EXPECTED_ENTITY_LENGTH' => '1024')), - array(511, array('HTTP_CONTENT_LENGTH' => '512')), - array(2047, array('HTTP_OC_TOTAL_LENGTH' => '2048', 'HTTP_CONTENT_LENGTH' => '1024')), + array(1023, array('X-EXPECTED-ENTITY-LENGTH' => '1024')), + array(511, array('CONTENT-LENGTH' => '512')), + array(2047, array('OC-TOTAL-LENGTH' => '2048', 'CONTENT-LENGTH' => '1024')), ); } public function lengthProvider() { return array( array(null, array()), - array(1024, array('HTTP_X_EXPECTED_ENTITY_LENGTH' => '1024')), - array(512, array('HTTP_CONTENT_LENGTH' => '512')), - array(2048, array('HTTP_OC_TOTAL_LENGTH' => '2048', 'HTTP_CONTENT_LENGTH' => '1024')), - array(4096, array('HTTP_OC_TOTAL_LENGTH' => '2048', 'HTTP_X_EXPECTED_ENTITY_LENGTH' => '4096')), + array(1024, array('X-EXPECTED-ENTITY-LENGTH' => '1024')), + array(512, array('CONTENT-LENGTH' => '512')), + array(2048, array('OC-TOTAL-LENGTH' => '2048', 'CONTENT-LENGTH' => '1024')), + array(4096, array('OC-TOTAL-LENGTH' => '2048', 'X-EXPECTED-ENTITY-LENGTH' => '4096')), ); } diff --git a/tests/lib/connector/sabre/tagsplugin.php b/tests/lib/connector/sabre/tagsplugin.php index 2afea061ec3..f8af73fecfb 100644 --- a/tests/lib/connector/sabre/tagsplugin.php +++ b/tests/lib/connector/sabre/tagsplugin.php @@ -42,7 +42,7 @@ class TagsPlugin extends \Test\TestCase { public function setUp() { parent::setUp(); $this->server = new \Sabre\DAV\Server(); - $this->tree = $this->getMockBuilder('\Sabre\DAV\ObjectTree') + $this->tree = $this->getMockBuilder('\Sabre\DAV\Tree') ->disableOriginalConstructor() ->getMock(); $this->tagger = $this->getMock('\OCP\ITags'); @@ -59,7 +59,7 @@ class TagsPlugin extends \Test\TestCase { * @dataProvider tagsGetPropertiesDataProvider */ public function testGetProperties($tags, $requestedProperties, $expectedProperties) { - $node = $this->getMockBuilder('\OC_Connector_Sabre_Node') + $node = $this->getMockBuilder('\OC\Connector\Sabre\Node') ->disableOriginalConstructor() ->getMock(); $node->expects($this->any()) @@ -76,29 +76,35 @@ class TagsPlugin extends \Test\TestCase { ->with($this->equalTo(array(123))) ->will($this->returnValue(array(123 => $tags))); - $returnedProperties = array(); - - $this->plugin->beforeGetProperties( - '', - $node, + $propFind = new \Sabre\DAV\PropFind( + '/dummyPath', $requestedProperties, - $returnedProperties + 0 ); - $this->assertEquals($expectedProperties, $returnedProperties); + $this->plugin->handleGetProperties( + $propFind, + $node + ); + + $result = $propFind->getResultForMultiStatus(); + + $this->assertEmpty($result[404]); + unset($result[404]); + $this->assertEquals($expectedProperties, $result); } /** * @dataProvider tagsGetPropertiesDataProvider */ public function testPreloadThenGetProperties($tags, $requestedProperties, $expectedProperties) { - $node1 = $this->getMockBuilder('\OC_Connector_Sabre_File') + $node1 = $this->getMockBuilder('\OC\Connector\Sabre\File') ->disableOriginalConstructor() ->getMock(); $node1->expects($this->any()) ->method('getId') ->will($this->returnValue(111)); - $node2 = $this->getMockBuilder('\OC_Connector_Sabre_File') + $node2 = $this->getMockBuilder('\OC\Connector\Sabre\File') ->disableOriginalConstructor() ->getMock(); $node2->expects($this->any()) @@ -113,7 +119,7 @@ class TagsPlugin extends \Test\TestCase { $expectedCallCount = 1; } - $node = $this->getMockBuilder('\OC_Connector_Sabre_Directory') + $node = $this->getMockBuilder('\OC\Connector\Sabre\Directory') ->disableOriginalConstructor() ->getMock(); $node->expects($this->any()) @@ -123,14 +129,9 @@ class TagsPlugin extends \Test\TestCase { ->method('getChildren') ->will($this->returnValue(array($node1, $node2))); - $this->tree->expects($this->once()) - ->method('getNodeForPath') - ->with('/subdir') - ->will($this->returnValue($node)); - $this->tagger->expects($this->exactly($expectedCallCount)) ->method('getTagsForObjects') - ->with($this->equalTo(array(111, 222))) + ->with($this->equalTo(array(123, 111, 222))) ->will($this->returnValue( array( 111 => $tags, @@ -138,22 +139,41 @@ class TagsPlugin extends \Test\TestCase { ) )); - $returnedProperties = array(); - - $this->plugin->beforeGetPropertiesForPath( + // simulate sabre recursive PROPFIND traversal + $propFindRoot = new \Sabre\DAV\PropFind( '/subdir', $requestedProperties, 1 ); - - $this->plugin->beforeGetProperties( + $propFind1 = new \Sabre\DAV\PropFind( '/subdir/test.txt', - $node1, $requestedProperties, - $returnedProperties + 0 + ); + $propFind2 = new \Sabre\DAV\PropFind( + '/subdir/test2.txt', + $requestedProperties, + 0 ); - $this->assertEquals($expectedProperties, $returnedProperties); + $this->plugin->handleGetProperties( + $propFindRoot, + $node + ); + $this->plugin->handleGetProperties( + $propFind1, + $node1 + ); + $this->plugin->handleGetProperties( + $propFind2, + $node2 + ); + + $result = $propFind1->getResultForMultiStatus(); + + $this->assertEmpty($result[404]); + unset($result[404]); + $this->assertEquals($expectedProperties, $result); } function tagsGetPropertiesDataProvider() { @@ -193,7 +213,9 @@ class TagsPlugin extends \Test\TestCase { array( array('tag1', 'tag2', self::TAG_FAVORITE), array(), - array(), + array( + 200 => array() + ), ), // request both with none set, receive both array( @@ -212,13 +234,18 @@ class TagsPlugin extends \Test\TestCase { public function testUpdateTags() { // this test will replace the existing tags "tagremove" with "tag1" and "tag2" // and keep "tagkeep" - $node = $this->getMockBuilder('\OC_Connector_Sabre_Node') + $node = $this->getMockBuilder('\OC\Connector\Sabre\Node') ->disableOriginalConstructor() ->getMock(); $node->expects($this->any()) ->method('getId') ->will($this->returnValue(123)); + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/dummypath') + ->will($this->returnValue($node)); + $this->tagger->expects($this->at(0)) ->method('getTagsForObjects') ->with($this->equalTo(array(123))) @@ -238,58 +265,109 @@ class TagsPlugin extends \Test\TestCase { ->with(123, 'tagremove'); // properties to set - $properties = array( + $propPatch = new \Sabre\DAV\PropPatch(array( self::TAGS_PROPERTYNAME => new \OC\Connector\Sabre\TagList(array('tag1', 'tag2', 'tagkeep')) - ); - $result = array(); + )); - $this->plugin->updateProperties( - $properties, - $result, - $node + $this->plugin->handleUpdateProperties( + '/dummypath', + $propPatch ); + $propPatch->commit(); + // all requested properties removed, as they were processed already - $this->assertEmpty($properties); + $this->assertEmpty($propPatch->getRemainingMutations()); + + $result = $propPatch->getResult(); + $this->assertEquals(200, $result[self::TAGS_PROPERTYNAME]); + $this->assertFalse(isset($result[self::FAVORITE_PROPERTYNAME])); + } + + public function testUpdateTagsFromScratch() { + $node = $this->getMockBuilder('\OC\Connector\Sabre\Node') + ->disableOriginalConstructor() + ->getMock(); + $node->expects($this->any()) + ->method('getId') + ->will($this->returnValue(123)); + + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/dummypath') + ->will($this->returnValue($node)); + + $this->tagger->expects($this->at(0)) + ->method('getTagsForObjects') + ->with($this->equalTo(array(123))) + ->will($this->returnValue(array())); + + // then tag as tag1 and tag2 + $this->tagger->expects($this->at(1)) + ->method('tagAs') + ->with(123, 'tag1'); + $this->tagger->expects($this->at(2)) + ->method('tagAs') + ->with(123, 'tag2'); - $this->assertEquals( - new \OC\Connector\Sabre\TagList(array('tag1', 'tag2', 'tagkeep')), - $result[200][self::TAGS_PROPERTYNAME] + // properties to set + $propPatch = new \Sabre\DAV\PropPatch(array( + self::TAGS_PROPERTYNAME => new \OC\Connector\Sabre\TagList(array('tag1', 'tag2', 'tagkeep')) + )); + + $this->plugin->handleUpdateProperties( + '/dummypath', + $propPatch ); - $this->assertFalse(isset($result[200][self::FAVORITE_PROPERTYNAME])); + + $propPatch->commit(); + + // all requested properties removed, as they were processed already + $this->assertEmpty($propPatch->getRemainingMutations()); + + $result = $propPatch->getResult(); + $this->assertEquals(200, $result[self::TAGS_PROPERTYNAME]); + $this->assertFalse(false, isset($result[self::FAVORITE_PROPERTYNAME])); } public function testUpdateFav() { // this test will replace the existing tags "tagremove" with "tag1" and "tag2" // and keep "tagkeep" - $node = $this->getMockBuilder('\OC_Connector_Sabre_Node') + $node = $this->getMockBuilder('\OC\Connector\Sabre\Node') ->disableOriginalConstructor() ->getMock(); $node->expects($this->any()) ->method('getId') ->will($this->returnValue(123)); + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/dummypath') + ->will($this->returnValue($node)); + // set favorite tag $this->tagger->expects($this->once()) ->method('tagAs') ->with(123, self::TAG_FAVORITE); // properties to set - $properties = array( + $propPatch = new \Sabre\DAV\PropPatch(array( self::FAVORITE_PROPERTYNAME => true - ); - $result = array(); - $this->plugin->updateProperties( - $properties, - $result, - $node + )); + + $this->plugin->handleUpdateProperties( + '/dummypath', + $propPatch ); + $propPatch->commit(); + // all requested properties removed, as they were processed already - $this->assertEmpty($properties); + $this->assertEmpty($propPatch->getRemainingMutations()); - $this->assertTrue($result[200][self::FAVORITE_PROPERTYNAME]); - $this->assertFalse(isset($result[200][self::TAGS_PROPERTYNAME])); + $result = $propPatch->getResult(); + $this->assertFalse(false, isset($result[self::TAGS_PROPERTYNAME])); + $this->assertEquals(200, isset($result[self::FAVORITE_PROPERTYNAME])); // unfavorite now // set favorite tag @@ -297,18 +375,24 @@ class TagsPlugin extends \Test\TestCase { ->method('unTag') ->with(123, self::TAG_FAVORITE); - $properties = array( + // properties to set + $propPatch = new \Sabre\DAV\PropPatch(array( self::FAVORITE_PROPERTYNAME => false + )); + + $this->plugin->handleUpdateProperties( + '/dummypath', + $propPatch ); - $result = array(); - $this->plugin->updateProperties( - $properties, - $result, - $node - ); - $this->assertFalse($result[200][self::FAVORITE_PROPERTYNAME]); - $this->assertFalse(isset($result[200][self::TAGS_PROPERTYNAME])); + $propPatch->commit(); + + // all requested properties removed, as they were processed already + $this->assertEmpty($propPatch->getRemainingMutations()); + + $result = $propPatch->getResult(); + $this->assertFalse(false, isset($result[self::TAGS_PROPERTYNAME])); + $this->assertEquals(200, isset($result[self::FAVORITE_PROPERTYNAME])); } } diff --git a/tests/lib/files/cache/changepropagator.php b/tests/lib/files/cache/changepropagator.php index 89bd9dfe80a..1b56da5e97c 100644 --- a/tests/lib/files/cache/changepropagator.php +++ b/tests/lib/files/cache/changepropagator.php @@ -23,12 +23,17 @@ class ChangePropagator extends \Test\TestCase { */ private $view; + /** + * @var \OC\Files\Storage\Storage + */ + private $storage; + protected function setUp() { parent::setUp(); - $storage = new Temporary(array()); + $this->storage = new Temporary(array()); $root = $this->getUniqueID('/'); - Filesystem::mount($storage, array(), $root); + Filesystem::mount($this->storage, array(), $root); $this->view = new View($root); $this->propagator = new \OC\Files\Cache\ChangePropagator($this->view); } @@ -71,4 +76,22 @@ class ChangePropagator extends \Test\TestCase { $this->assertNotSame($oldInfo2->getEtag(), $newInfo2->getEtag()); $this->assertNotSame($oldInfo3->getEtag(), $newInfo3->getEtag()); } + + public function testDontLowerMtime() { + $time = time(); + $this->view->mkdir('/foo'); + $this->view->mkdir('/foo/bar'); + + $cache = $this->storage->getCache(); + $cache->put('', ['mtime' => $time - 50]); + $cache->put('foo', ['mtime' => $time - 150]); + $cache->put('foo/bar', ['mtime' => $time - 250]); + + $this->propagator->addChange('/foo/bar/foo'); + $this->propagator->propagateChanges($time - 100); + + $this->assertEquals(50, $time - $cache->get('')['mtime']); + $this->assertEquals(100, $time - $cache->get('foo')['mtime']); + $this->assertEquals(100, $time - $cache->get('foo/bar')['mtime']); + } } diff --git a/tests/lib/files/cache/updater.php b/tests/lib/files/cache/updater.php index 01b036de5d8..970af2e68df 100644 --- a/tests/lib/files/cache/updater.php +++ b/tests/lib/files/cache/updater.php @@ -146,4 +146,34 @@ class Updater extends \Test\TestCase { $this->assertEquals($cached['size'], $cachedTarget['size']); $this->assertEquals($cached['fileid'], $cachedTarget['fileid']); } + + public function testNewFileDisabled() { + $this->storage->file_put_contents('foo.txt', 'bar'); + $this->assertFalse($this->cache->inCache('foo.txt')); + + $this->updater->disable(); + $this->updater->update('/foo.txt'); + + $this->assertFalse($this->cache->inCache('foo.txt')); + } + + public function testMoveDisabled() { + $this->storage->file_put_contents('foo.txt', 'qwerty'); + $this->updater->update('foo.txt'); + + $this->assertTrue($this->cache->inCache('foo.txt')); + $this->assertFalse($this->cache->inCache('bar.txt')); + $cached = $this->cache->get('foo.txt'); + + $this->storage->rename('foo.txt', 'bar.txt'); + + $this->assertTrue($this->cache->inCache('foo.txt')); + $this->assertFalse($this->cache->inCache('bar.txt')); + + $this->updater->disable(); + $this->updater->rename('foo.txt', 'bar.txt'); + + $this->assertTrue($this->cache->inCache('foo.txt')); + $this->assertFalse($this->cache->inCache('bar.txt')); + } } diff --git a/tests/lib/files/cache/updaterlegacy.php b/tests/lib/files/cache/updaterlegacy.php index 7cf4dc6df5f..99cacca8e95 100644 --- a/tests/lib/files/cache/updaterlegacy.php +++ b/tests/lib/files/cache/updaterlegacy.php @@ -284,6 +284,7 @@ class UpdaterLegacy extends \Test\TestCase { $time = 1371006070; $barCachedData = $this->cache->get('folder/bar.txt'); $folderCachedData = $this->cache->get('folder'); + $this->cache->put('', ['mtime' => $time - 100]); Filesystem::touch('folder/bar.txt', $time); $cachedData = $this->cache->get('folder/bar.txt'); $this->assertInternalType('string', $barCachedData['etag']); @@ -314,6 +315,7 @@ class UpdaterLegacy extends \Test\TestCase { $fooCachedData = $cache2->get('foo.txt'); $cachedData = $cache2->get('foo.txt'); $time = 1371006070; + $this->cache->put('folder', ['mtime' => $time - 100]); Filesystem::touch('folder/substorage/foo.txt', $time); $cachedData = $cache2->get('foo.txt'); $this->assertInternalType('string', $fooCachedData['etag']); diff --git a/tests/lib/files/node/node.php b/tests/lib/files/node/node.php index 49a2006c767..01ed84c4a06 100644 --- a/tests/lib/files/node/node.php +++ b/tests/lib/files/node/node.php @@ -340,4 +340,19 @@ class Node extends \Test\TestCase { $node = new \OC\Files\Node\Node($root, $view, '/bar/foo'); $node->touch(100); } + + /** + * @expectedException \OCP\Files\InvalidPathException + */ + public function testInvalidPath() { + $manager = $this->getMock('\OC\Files\Mount\Manager'); + /** + * @var \OC\Files\View | \PHPUnit_Framework_MockObject_MockObject $view + */ + $view = $this->getMock('\OC\Files\View'); + $root = $this->getMock('\OC\Files\Node\Root', array(), array($manager, $view, $this->user)); + + $node = new \OC\Files\Node\Node($root, $view, '/../foo'); + $node->getFileInfo(); + } } diff --git a/tests/lib/files/objectstore/noopscanner.php b/tests/lib/files/objectstore/noopscanner.php new file mode 100644 index 00000000000..f860c03cb18 --- /dev/null +++ b/tests/lib/files/objectstore/noopscanner.php @@ -0,0 +1,76 @@ +<?php +/** + * ownCloud + * + * @author Joas Schilling + * @copyright 2015 Joas Schilling nickvergessen@owncloud.com + * + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +namespace Test\Files\Cache; + +class NoopScanner extends \Test\TestCase { + /** @var \OC\Files\Storage\Storage $storage */ + private $storage; + + /** @var \OC\Files\ObjectStore\NoopScanner $scanner */ + private $scanner; + + protected function setUp() { + parent::setUp(); + + $this->storage = new \OC\Files\Storage\Temporary(array()); + $this->scanner = new \OC\Files\ObjectStore\NoopScanner($this->storage); + } + + function testFile() { + $data = "dummy file data\n"; + $this->storage->file_put_contents('foo.txt', $data); + + $this->assertEquals( + [], + $this->scanner->scanFile('foo.txt'), + 'Asserting that no error occurred while scanFile()' + ); + } + + private function fillTestFolders() { + $textData = "dummy file data\n"; + $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); + $this->storage->mkdir('folder'); + $this->storage->file_put_contents('foo.txt', $textData); + $this->storage->file_put_contents('foo.png', $imgData); + $this->storage->file_put_contents('folder/bar.txt', $textData); + } + + function testFolder() { + $this->fillTestFolders(); + + $this->assertEquals( + [], + $this->scanner->scan(''), + 'Asserting that no error occurred while scan()' + ); + } + + function testBackgroundScan() { + $this->fillTestFolders(); + $this->storage->mkdir('folder2'); + $this->storage->file_put_contents('folder2/bar.txt', 'foobar'); + + $this->assertEquals( + [], + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW), + 'Asserting that no error occurred while scan(SCAN_SHALLOW)' + ); + + $this->scanner->backgroundScan(); + + $this->assertTrue( + true, + 'Asserting that no error occurred while backgroundScan()' + ); + } +} diff --git a/tests/lib/files/objectstore/swift.php b/tests/lib/files/objectstore/swift.php index 30c60598277..0aaf7d906dd 100644 --- a/tests/lib/files/objectstore/swift.php +++ b/tests/lib/files/objectstore/swift.php @@ -23,8 +23,6 @@ namespace OCA\ObjectStore\Tests\Unit; use OC\Files\ObjectStore\ObjectStoreStorage; use OC\Files\ObjectStore\Swift as ObjectStoreToTest; -use PHPUnit_Framework_TestCase; - //class Swift extends PHPUnit_Framework_TestCase { class Swift extends \Test\Files\Storage\Storage { diff --git a/tests/lib/files/pathverificationtest.php b/tests/lib/files/pathverificationtest.php new file mode 100644 index 00000000000..1a802a48f57 --- /dev/null +++ b/tests/lib/files/pathverificationtest.php @@ -0,0 +1,223 @@ +<?php +/** + * Copyright (c) 2015 Thomas Müller <deepdiver@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. */ + +namespace Test\Files; + +use OC\Files\Storage\Local; +use OC\Files\View; + +class PathVerification extends \Test\TestCase { + + /** + * @var \OC\Files\View + */ + private $view; + + protected function setUp() { + parent::setUp(); + $this->view = new View(); + } + + /** + * @dataProvider providesEmptyFiles + * @expectedException \OCP\Files\InvalidPathException + * @expectedExceptionMessage Empty filename is not allowed + */ + public function testPathVerificationEmptyFileName($fileName) { + $this->view->verifyPath('', $fileName); + } + + public function providesEmptyFiles() { + return [ + [''], + [' '], + ]; + } + + /** + * @dataProvider providesDotFiles + * @expectedException \OCP\Files\InvalidPathException + * @expectedExceptionMessage Dot files are not allowed + */ + public function testPathVerificationDotFiles($fileName) { + $this->view->verifyPath('', $fileName); + } + + public function providesDotFiles() { + return [ + ['.'], + ['..'], + [' .'], + [' ..'], + ['. '], + ['.. '], + [' . '], + [' .. '], + ]; + } + + /** + * @dataProvider providesAstralPlane + * @expectedException \OCP\Files\InvalidPathException + * @expectedExceptionMessage 4-byte characters are not supported in file names + */ + public function testPathVerificationAstralPlane($fileName) { + $this->view->verifyPath('', $fileName); + } + + public function providesAstralPlane() { + return [ + // this is the monkey emoji - http://en.wikipedia.org/w/index.php?title=%F0%9F%90%B5&redirect=no + ['🐵'], + ]; + } + + /** + * @dataProvider providesInvalidCharsWindows + * @expectedException \OCP\Files\InvalidCharacterInPathException + */ + public function testPathVerificationInvalidCharsWindows($fileName) { + $storage = new Local(['datadir' => '']); + + $fileName = " 123{$fileName}456 "; + \Test_Helper::invokePrivate($storage, 'verifyWindowsPath', [$fileName]); + } + + public function providesInvalidCharsWindows() { + return [ + [\chr(0)], + [\chr(1)], + [\chr(2)], + [\chr(3)], + [\chr(4)], + [\chr(5)], + [\chr(6)], + [\chr(7)], + [\chr(8)], + [\chr(9)], + [\chr(10)], + [\chr(11)], + [\chr(12)], + [\chr(13)], + [\chr(14)], + [\chr(15)], + [\chr(16)], + [\chr(17)], + [\chr(18)], + [\chr(19)], + [\chr(20)], + [\chr(21)], + [\chr(22)], + [\chr(23)], + [\chr(24)], + [\chr(25)], + [\chr(26)], + [\chr(27)], + [\chr(28)], + [\chr(29)], + [\chr(30)], + [\chr(31)], + ['<'], + ['>'], + [':'], + ['"'], + ['/'], + ['\\'], + ['|'], + ['?'], + ['*'], + ]; + } + + /** + * @dataProvider providesInvalidCharsPosix + * @expectedException \OCP\Files\InvalidCharacterInPathException + */ + public function testPathVerificationInvalidCharsPosix($fileName) { + $storage = new Local(['datadir' => '']); + + $fileName = " 123{$fileName}456 "; + \Test_Helper::invokePrivate($storage, 'verifyWindowsPath', [$fileName]); + } + + public function providesInvalidCharsPosix() { + return [ + [\chr(0)], + [\chr(1)], + [\chr(2)], + [\chr(3)], + [\chr(4)], + [\chr(5)], + [\chr(6)], + [\chr(7)], + [\chr(8)], + [\chr(9)], + [\chr(10)], + [\chr(11)], + [\chr(12)], + [\chr(13)], + [\chr(14)], + [\chr(15)], + [\chr(16)], + [\chr(17)], + [\chr(18)], + [\chr(19)], + [\chr(20)], + [\chr(21)], + [\chr(22)], + [\chr(23)], + [\chr(24)], + [\chr(25)], + [\chr(26)], + [\chr(27)], + [\chr(28)], + [\chr(29)], + [\chr(30)], + [\chr(31)], + ['/'], + ['\\'], + ]; + } + + /** + * @dataProvider providesReservedNamesWindows + * @expectedException \OCP\Files\ReservedWordException + */ + public function testPathVerificationReservedNamesWindows($fileName) { + $storage = new Local(['datadir' => '']); + + \Test_Helper::invokePrivate($storage, 'verifyWindowsPath', [$fileName]); + } + + public function providesReservedNamesWindows() { + return [ + [' CON '], + ['prn '], + ['AUX'], + ['NUL'], + ['COM1'], + ['COM2'], + ['COM3'], + ['COM4'], + ['COM5'], + ['COM6'], + ['COM7'], + ['COM8'], + ['COM9'], + ['LPT1'], + ['LPT2'], + ['LPT3'], + ['LPT4'], + ['LPT5'], + ['LPT6'], + ['LPT7'], + ['LPT8'], + ['LPT9'] + ]; + } + +} diff --git a/tests/lib/files/storage/wrapper/quota.php b/tests/lib/files/storage/wrapper/quota.php index dc4de4697db..8ca8f308b71 100644 --- a/tests/lib/files/storage/wrapper/quota.php +++ b/tests/lib/files/storage/wrapper/quota.php @@ -99,6 +99,28 @@ class Quota extends \Test\Files\Storage\Storage { $this->assertEquals('foobarqwe', $instance->file_get_contents('foo')); } + public function testStreamCopyWithEnoughSpace() { + $instance = $this->getLimitedStorage(16); + $inputStream = fopen('data://text/plain,foobarqwerty', 'r'); + $outputStream = $instance->fopen('foo', 'w+'); + list($count, $result) = \OC_Helper::streamCopy($inputStream, $outputStream); + $this->assertEquals(12, $count); + $this->assertTrue($result); + fclose($inputStream); + fclose($outputStream); + } + + public function testStreamCopyNotEnoughSpace() { + $instance = $this->getLimitedStorage(9); + $inputStream = fopen('data://text/plain,foobarqwerty', 'r'); + $outputStream = $instance->fopen('foo', 'w+'); + list($count, $result) = \OC_Helper::streamCopy($inputStream, $outputStream); + $this->assertEquals(9, $count); + $this->assertFalse($result); + fclose($inputStream); + fclose($outputStream); + } + public function testReturnFalseWhenFopenFailed() { $failStorage = $this->getMock( '\OC\Files\Storage\Local', diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index f6af59d52be..db39df7d16b 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -872,6 +872,57 @@ class View extends \Test\TestCase { $this->assertEquals($time, $view->filemtime('/test/sub/storage/foo/bar.txt')); } + public function testRenameFailDeleteTargetKeepSource() { + $this->doTestCopyRenameFail('rename'); + } + + public function testCopyFailDeleteTargetKeepSource() { + $this->doTestCopyRenameFail('copy'); + } + + private function doTestCopyRenameFail($operation) { + $storage1 = new Temporary(array()); + $storage2 = new Temporary(array()); + $storage2 = new \OC\Files\Storage\Wrapper\Quota(array('storage' => $storage2, 'quota' => 9)); + $storage1->mkdir('sub'); + $storage1->file_put_contents('foo.txt', '0123456789ABCDEFGH'); + $storage1->mkdir('dirtomove'); + $storage1->file_put_contents('dirtomove/indir1.txt', '0123456'); // fits + $storage1->file_put_contents('dirtomove/indir2.txt', '0123456789ABCDEFGH'); // doesn't fit + $storage2->file_put_contents('existing.txt', '0123'); + $storage1->getScanner()->scan(''); + $storage2->getScanner()->scan(''); + \OC\Files\Filesystem::mount($storage1, array(), '/test/'); + \OC\Files\Filesystem::mount($storage2, array(), '/test/sub/storage'); + + // move file + $view = new \OC\Files\View(''); + $this->assertTrue($storage1->file_exists('foo.txt')); + $this->assertFalse($storage2->file_exists('foo.txt')); + $this->assertFalse($view->$operation('/test/foo.txt', '/test/sub/storage/foo.txt')); + $this->assertFalse($storage2->file_exists('foo.txt')); + $this->assertFalse($storage2->getCache()->get('foo.txt')); + $this->assertTrue($storage1->file_exists('foo.txt')); + + // if target exists, it will be deleted too + $this->assertFalse($view->$operation('/test/foo.txt', '/test/sub/storage/existing.txt')); + $this->assertFalse($storage2->file_exists('existing.txt')); + $this->assertFalse($storage2->getCache()->get('existing.txt')); + $this->assertTrue($storage1->file_exists('foo.txt')); + + // move folder + $this->assertFalse($view->$operation('/test/dirtomove/', '/test/sub/storage/dirtomove/')); + // since the move failed, the full source tree is kept + $this->assertTrue($storage1->file_exists('dirtomove/indir1.txt')); + // but the target file stays + $this->assertTrue($storage2->file_exists('dirtomove/indir1.txt')); + // second file not moved/copied + $this->assertTrue($storage1->file_exists('dirtomove/indir2.txt')); + $this->assertFalse($storage2->file_exists('dirtomove/indir2.txt')); + $this->assertFalse($storage2->getCache()->get('dirtomove/indir2.txt')); + + } + public function testDeleteFailKeepCache() { /** * @var \PHPUnit_Framework_MockObject_MockObject | \OC\Files\Storage\Temporary $storage @@ -894,4 +945,34 @@ class View extends \Test\TestCase { $this->assertFalse($view->unlink('foo.txt')); $this->assertTrue($cache->inCache('foo.txt')); } + + function directoryTraversalProvider() { + return [ + ['../test/'], + ['..\\test\\my/../folder'], + ['/test/my/../foo\\'], + ]; + } + + /** + * @dataProvider directoryTraversalProvider + * @expectedException \Exception + * @param string $root + */ + public function testConstructDirectoryTraversalException($root) { + new \OC\Files\View($root); + } + + public function testRenameOverWrite() { + $storage = new Temporary(array()); + $scanner = $storage->getScanner(); + $storage->mkdir('sub'); + $storage->mkdir('foo'); + $storage->file_put_contents('foo.txt', 'asd'); + $storage->file_put_contents('foo/bar.txt', 'asd'); + $scanner->scan(''); + \OC\Files\Filesystem::mount($storage, array(), '/test/'); + $view = new \OC\Files\View(''); + $this->assertTrue($view->rename('/test/foo.txt', '/test/foo/bar.txt')); + } } diff --git a/tests/lib/l10n.php b/tests/lib/l10n.php index 2235581add8..0307dd459e5 100644 --- a/tests/lib/l10n.php +++ b/tests/lib/l10n.php @@ -173,4 +173,20 @@ class Test_L10n extends \Test\TestCase { array(null, null, 'en'), ); } + + public function testGetLanguageCode() { + $l = OC_L10N::get('lib', 'de'); + $this->assertEquals('de', $l->getLanguageCode()); + } + + public function testFactoryGetLanguageCode() { + $factory = new \OC\L10N\Factory(); + $l = $factory->get('lib', 'de'); + $this->assertEquals('de', $l->getLanguageCode()); + } + + public function testServiceGetLanguageCode() { + $l = \OC::$server->getL10N('lib', 'de'); + $this->assertEquals('de', $l->getLanguageCode()); + } } diff --git a/tests/lib/memcache/arraycache.php b/tests/lib/memcache/arraycache.php new file mode 100644 index 00000000000..1db673da2a8 --- /dev/null +++ b/tests/lib/memcache/arraycache.php @@ -0,0 +1,17 @@ +<?php + +/** + * Copyright (c) 2015 Joas Schilling <nickvergessen@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Memcache; + +class ArrayCache extends Cache { + protected function setUp() { + parent::setUp(); + $this->instance = new \OC\Memcache\ArrayCache(''); + } +} diff --git a/tests/lib/memcache/factory.php b/tests/lib/memcache/factory.php new file mode 100644 index 00000000000..4ce032abbe8 --- /dev/null +++ b/tests/lib/memcache/factory.php @@ -0,0 +1,110 @@ +<?php +/** + * @author Robin McCorkell <rmccorkell@karoshi.org.uk> + * + * @copyright Copyright (c) 2015, 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/> + * + */ +namespace Test\Memcache; + +class Test_Factory_Available_Cache1 { + public function __construct($prefix = '') { + } + + public static function isAvailable() { + return true; + } +} + +class Test_Factory_Available_Cache2 { + public function __construct($prefix = '') { + } + + public static function isAvailable() { + return true; + } +} + +class Test_Factory_Unavailable_Cache1 { + public function __construct($prefix = '') { + } + + public static function isAvailable() { + return false; + } +} + +class Test_Factory_Unavailable_Cache2 { + public function __construct($prefix = '') { + } + + public static function isAvailable() { + return false; + } +} + +class Test_Factory extends \Test\TestCase { + const AVAILABLE1 = '\\Test\\Memcache\\Test_Factory_Available_Cache1'; + const AVAILABLE2 = '\\Test\\Memcache\\Test_Factory_Available_Cache2'; + const UNAVAILABLE1 = '\\Test\\Memcache\\Test_Factory_Unavailable_Cache1'; + const UNAVAILABLE2 = '\\Test\\Memcache\\Test_Factory_Unavailable_Cache2'; + + public function cacheAvailabilityProvider() { + return [ + [ + // local and distributed available + self::AVAILABLE1, self::AVAILABLE2, + self::AVAILABLE1, self::AVAILABLE2 + ], + [ + // local available, distributed unavailable + self::AVAILABLE1, self::UNAVAILABLE1, + self::AVAILABLE1, self::AVAILABLE1 + ], + [ + // local unavailable, distributed available + self::UNAVAILABLE1, self::AVAILABLE1, + \OC\Memcache\Factory::NULL_CACHE, self::AVAILABLE1 + ], + [ + // local and distributed unavailable + self::UNAVAILABLE1, self::UNAVAILABLE2, + \OC\Memcache\Factory::NULL_CACHE, \OC\Memcache\Factory::NULL_CACHE + ], + [ + // local and distributed null + null, null, + \OC\Memcache\Factory::NULL_CACHE, \OC\Memcache\Factory::NULL_CACHE + ], + [ + // local available, distributed null (most common scenario) + self::AVAILABLE1, null, + self::AVAILABLE1, self::AVAILABLE1 + ] + ]; + } + + /** + * @dataProvider cacheAvailabilityProvider + */ + public function testCacheAvailability($localCache, $distributedCache, + $expectedLocalCache, $expectedDistributedCache) + { + $factory = new \OC\Memcache\Factory('abc', $localCache, $distributedCache); + $this->assertTrue(is_a($factory->createLocal(), $expectedLocalCache)); + $this->assertTrue(is_a($factory->createDistributed(), $expectedDistributedCache)); + } +} diff --git a/tests/lib/naturalsort.php b/tests/lib/naturalsort.php index e022a855309..8fcbc6f5fd3 100644 --- a/tests/lib/naturalsort.php +++ b/tests/lib/naturalsort.php @@ -8,27 +8,32 @@ class Test_NaturalSort extends \Test\TestCase { - public function setUp() { - parent::setUp(); - + /** + * @dataProvider naturalSortDataProvider + */ + public function testNaturalSortCompare($array, $sorted) + { if(!class_exists('Collator')) { - $this->markTestSkipped('The intl module is not available, natural sorting will not work as expected.'); + $this->markTestSkipped('The intl module is not available, natural sorting might not work as expected.'); return; } + $comparator = \OC\NaturalSort::getInstance(); + usort($array, array($comparator, 'compare')); + $this->assertEquals($sorted, $array); } /** - * @dataProvider naturalSortDataProvider - */ - public function testNaturalSortCompare($array, $sorted) + * @dataProvider defaultCollatorDataProvider + */ + public function testDefaultCollatorCompare($array, $sorted) { - $comparator = \OC\NaturalSort::getInstance(); + $comparator = new \OC\NaturalSort(new \OC\NaturalSort_DefaultCollator()); usort($array, array($comparator, 'compare')); $this->assertEquals($sorted, $array); } /** - * Data provider for natural sort. + * Data provider for natural sorting with php5-intl's Collator. * Must provide the same result as in core/js/tests/specs/coreSpec.js * @return array test cases */ @@ -181,4 +186,85 @@ class Test_NaturalSort extends \Test\TestCase { ), ); } + + /** + * Data provider for natural sorting with \OC\NaturalSort_DefaultCollator. + * Must provide the same result as in core/js/tests/specs/coreSpec.js + * @return array test cases + */ + public function defaultCollatorDataProvider() + { + return array( + // different casing + array( + // unsorted + array( + 'aaa', + 'bbb', + 'BBB', + 'AAA' + ), + // sorted + array( + 'aaa', + 'AAA', + 'bbb', + 'BBB' + ) + ), + // numbers + array( + // unsorted + array( + '124.txt', + 'abc1', + '123.txt', + 'abc', + 'abc2', + 'def (2).txt', + 'ghi 10.txt', + 'abc12', + 'def.txt', + 'def (1).txt', + 'ghi 2.txt', + 'def (10).txt', + 'abc10', + 'def (12).txt', + 'z', + 'ghi.txt', + 'za', + 'ghi 1.txt', + 'ghi 12.txt', + 'zz', + '15.txt', + '15b.txt', + ), + // sorted + array( + '15.txt', + '15b.txt', + '123.txt', + '124.txt', + 'abc', + 'abc1', + 'abc2', + 'abc10', + 'abc12', + 'def.txt', + 'def (1).txt', + 'def (2).txt', + 'def (10).txt', + 'def (12).txt', + 'ghi.txt', + 'ghi 1.txt', + 'ghi 2.txt', + 'ghi 10.txt', + 'ghi 12.txt', + 'z', + 'za', + 'zz', + ) + ), + ); + } } diff --git a/tests/lib/repair/dropoldtables.php b/tests/lib/repair/dropoldtables.php new file mode 100644 index 00000000000..244d8837949 --- /dev/null +++ b/tests/lib/repair/dropoldtables.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright (c) 2015 Joas Schilling <nickvergessen@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Repair; + +/** + * Tests for the dropping old tables + * + * @see \OC\Repair\DropOldTables + */ +class DropOldTables extends \Test\TestCase { + /** @var \OCP\IDBConnection */ + protected $connection; + + protected function setUp() { + parent::setUp(); + + $this->connection = \OC::$server->getDatabaseConnection(); + $manager = new \OC\DB\MDB2SchemaManager($this->connection); + $manager->createDbFromStructure(__DIR__ . '/fixtures/dropoldtables.xml'); + } + + public function testRun() { + $this->assertFalse($this->connection->tableExists('sharing'), 'Asserting that the table oc_sharing does not exist before repairing'); + $this->assertTrue($this->connection->tableExists('permissions'), 'Asserting that the table oc_permissions does exist before repairing'); + + $repair = new \OC\Repair\DropOldTables($this->connection); + $repair->run(); + + $this->assertFalse($this->connection->tableExists('sharing'), 'Asserting that the table oc_sharing does not exist after repairing'); + $this->assertFalse($this->connection->tableExists('permissions'), 'Asserting that the table oc_permissions does not exist after repairing'); + } +} diff --git a/tests/lib/repair/fixtures/dropoldtables.xml b/tests/lib/repair/fixtures/dropoldtables.xml new file mode 100644 index 00000000000..6c42a8f90a7 --- /dev/null +++ b/tests/lib/repair/fixtures/dropoldtables.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8" ?> +<database> + + <name>*dbname*</name> + <create>true</create> + <overwrite>false</overwrite> + + <charset>utf8</charset> + + <table> + + <name>*dbprefix*permissions</name> + + <declaration> + <field> + <name>textfield</name> + <type>text</type> + <default>foo</default> + <notnull>true</notnull> + <length>32</length> + </field> + </declaration> + </table> +</database> diff --git a/tests/lib/repair/repairlegacystorage.php b/tests/lib/repair/repairlegacystorage.php index f08393300e1..4167ddff85a 100644 --- a/tests/lib/repair/repairlegacystorage.php +++ b/tests/lib/repair/repairlegacystorage.php @@ -24,6 +24,8 @@ class TestRepairLegacyStorages extends \Test\TestCase { private $legacyStorageId; private $newStorageId; + private $warnings; + protected function setUp() { parent::setUp(); @@ -32,6 +34,12 @@ class TestRepairLegacyStorages extends \Test\TestCase { $this->oldDataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/'); $this->repair = new \OC\Repair\RepairLegacyStorages($this->config, $this->connection); + + $this->warnings = []; + + $this->repair->listen('\OC\Repair', 'warning', function ($description){ + $this->warnings[] = $description; + }); } protected function tearDown() { @@ -181,21 +189,16 @@ class TestRepairLegacyStorages extends \Test\TestCase { $this->createData($this->legacyStorageId); $this->createData($this->newStorageId); - try { - $thrown = false; - $this->repair->run(); - } - catch (\OC\RepairException $e) { - $thrown = true; - } + $this->repair->run(); - $this->assertTrue($thrown); + $this->assertEquals(2, count($this->warnings)); + $this->assertEquals('Could not repair legacy storage ', substr(current($this->warnings), 0, 32)); // storages left alone $this->assertEquals($legacyStorageNumId, $this->getStorageId($this->legacyStorageId)); $this->assertEquals($newStorageNumId, $this->getStorageId($this->newStorageId)); - // did not set the done flag + // do not set the done flag $this->assertNotEquals('yes', $this->config->getAppValue('core', 'repairlegacystoragesdone')); } diff --git a/tests/lib/request.php b/tests/lib/request.php deleted file mode 100644 index dd6d1e47cd5..00000000000 --- a/tests/lib/request.php +++ /dev/null @@ -1,333 +0,0 @@ -<?php -/** - * Copyright (c) 2013 Thomas Müller <thomas.mueller@tmit.eu> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -class Test_Request extends \Test\TestCase { - - protected function setUp() { - parent::setUp(); - - OC::$server->getConfig()->setSystemValue('overwritewebroot', '/domain.tld/ownCloud'); - - OC::$server->getConfig()->setSystemValue('trusted_proxies', array()); - OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array()); - } - - protected function tearDown() { - OC::$server->getConfig()->setSystemValue('overwritewebroot', ''); - OC::$server->getConfig()->setSystemValue('trusted_proxies', array()); - OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array()); - - parent::tearDown(); - } - - public function testScriptNameOverWrite() { - $_SERVER['REMOTE_ADDR'] = '10.0.0.1'; - $_SERVER['SCRIPT_FILENAME'] = __FILE__; - - $scriptName = OC_Request::scriptName(); - $this->assertEquals('/domain.tld/ownCloud/tests/lib/request.php', $scriptName); - } - - public function testGetRemoteAddress() { - $_SERVER['REMOTE_ADDR'] = '10.0.0.2'; - $_SERVER['HTTP_X_FORWARDED'] = '10.4.0.5, 10.4.0.4'; - $_SERVER['HTTP_X_FORWARDED_FOR'] = '192.168.0.233'; - - // Without having specified a trusted remote address - $this->assertEquals('10.0.0.2', OC_Request::getRemoteAddress()); - - // With specifying a trusted remote address but no trusted header - OC::$server->getConfig()->setSystemValue('trusted_proxies', array('10.0.0.2')); - $this->assertEquals('10.0.0.2', OC_Request::getRemoteAddress()); - - // With specifying a trusted remote address and trusted headers - OC::$server->getConfig()->setSystemValue('trusted_proxies', array('10.0.0.2')); - OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array('HTTP_X_FORWARDED')); - $this->assertEquals('10.4.0.5', OC_Request::getRemoteAddress()); - OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED')); - $this->assertEquals('192.168.0.233', OC_Request::getRemoteAddress()); - - // With specifying multiple trusted remote addresses and trusted headers - OC::$server->getConfig()->setSystemValue('trusted_proxies', array('10.3.4.2', '10.0.0.2', '127.0.3.3')); - OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array('HTTP_X_FORWARDED')); - $this->assertEquals('10.4.0.5', OC_Request::getRemoteAddress()); - OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED')); - $this->assertEquals('192.168.0.233', OC_Request::getRemoteAddress()); - } - - /** - * @dataProvider rawPathInfoProvider - * @param $expected - * @param $requestUri - * @param $scriptName - */ - public function testRawPathInfo($expected, $requestUri, $scriptName) { - $_SERVER['REQUEST_URI'] = $requestUri; - $_SERVER['SCRIPT_NAME'] = $scriptName; - $rawPathInfo = OC_Request::getRawPathInfo(); - $this->assertEquals($expected, $rawPathInfo); - } - - function rawPathInfoProvider() { - return array( - array('/core/ajax/translations.php', 'index.php/core/ajax/translations.php', 'index.php'), - array('/core/ajax/translations.php', '/index.php/core/ajax/translations.php', '/index.php'), - array('/core/ajax/translations.php', '//index.php/core/ajax/translations.php', '/index.php'), - array('', '/oc/core', '/oc/core/index.php'), - array('', '/oc/core/', '/oc/core/index.php'), - array('', '/oc/core/index.php', '/oc/core/index.php'), - array('/core/ajax/translations.php', '/core/ajax/translations.php', 'index.php'), - array('/core/ajax/translations.php', '//core/ajax/translations.php', '/index.php'), - array('/core/ajax/translations.php', '/oc/core/ajax/translations.php', '/oc/index.php'), - array('/core/ajax/translations.php', '/oc//index.php/core/ajax/translations.php', '/oc/index.php'), - array('/1', '/oc/core/1', '/oc/core/index.php'), - ); - } - - /** - * @dataProvider rawPathInfoThrowsExceptionProvider - * @expectedException Exception - * - * @param $requestUri - * @param $scriptName - */ - public function testRawPathInfoThrowsException($requestUri, $scriptName) { - $_SERVER['REQUEST_URI'] = $requestUri; - $_SERVER['SCRIPT_NAME'] = $scriptName; - OC_Request::getRawPathInfo(); - } - - function rawPathInfoThrowsExceptionProvider() { - return array( - array('/oc/core1', '/oc/core/index.php'), - ); - } - - /** - * @dataProvider userAgentProvider - */ - public function testUserAgent($testAgent, $userAgent, $matches) { - $_SERVER['HTTP_USER_AGENT'] = $testAgent; - $this->assertEquals($matches, OC_Request::isUserAgent($userAgent)); - } - - function userAgentProvider() { - return array( - array( - 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', - OC_Request::USER_AGENT_IE, - true - ), - array( - 'Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0', - OC_Request::USER_AGENT_IE, - false - ), - array( - 'Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36', - OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME, - true - ), - array( - 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', - OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME, - false - ), - // test two values - array( - 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', - array( - OC_Request::USER_AGENT_IE, - OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME, - ), - true - ), - array( - 'Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36', - array( - OC_Request::USER_AGENT_IE, - OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME, - ), - true - ), - array( - 'Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0', - OC_Request::USER_AGENT_FREEBOX, - false - ), - array( - 'Mozilla/5.0', - OC_Request::USER_AGENT_FREEBOX, - true - ), - array( - 'Fake Mozilla/5.0', - OC_Request::USER_AGENT_FREEBOX, - false - ), - ); - } - - public function testInsecureServerHost() { - unset($_SERVER['HTTP_X_FORWARDED_HOST']); - unset($_SERVER['HTTP_HOST']); - unset($_SERVER['SERVER_NAME']); - $_SERVER['SERVER_NAME'] = 'from.server.name:8080'; - $host = OC_Request::insecureServerHost(); - $this->assertEquals('from.server.name:8080', $host); - - $_SERVER['HTTP_HOST'] = 'from.host.header:8080'; - $host = OC_Request::insecureServerHost(); - $this->assertEquals('from.host.header:8080', $host); - - $_SERVER['HTTP_X_FORWARDED_HOST'] = 'from.forwarded.host:8080'; - $host = OC_Request::insecureServerHost(); - $this->assertEquals('from.forwarded.host:8080', $host); - - $_SERVER['HTTP_X_FORWARDED_HOST'] = 'from.forwarded.host2:8080,another.one:9000'; - $host = OC_Request::insecureServerHost(); - $this->assertEquals('from.forwarded.host2:8080', $host); - - // clean up - unset($_SERVER['HTTP_X_FORWARDED_HOST']); - unset($_SERVER['HTTP_HOST']); - unset($_SERVER['SERVER_NAME']); - } - - public function testGetOverwriteHost() { - unset($_SERVER['REMOTE_ADDR']); - OC_Config::deleteKey('overwritecondaddr'); - OC_Config::deleteKey('overwritehost'); - $host = OC_Request::getOverwriteHost(); - $this->assertNull($host); - - OC_Config::setValue('overwritehost', ''); - $host = OC_Request::getOverwriteHost(); - $this->assertNull($host); - - OC_Config::setValue('overwritehost', 'host.one.test:8080'); - $host = OC_Request::getOverwriteHost(); - $this->assertEquals('host.one.test:8080', $host); - - $_SERVER['REMOTE_ADDR'] = 'somehost.test:8080'; - OC_Config::setValue('overwritecondaddr', '^somehost\..*$'); - $host = OC_Request::getOverwriteHost(); - $this->assertEquals('host.one.test:8080', $host); - - OC_Config::setValue('overwritecondaddr', '^somethingelse.*$'); - $host = OC_Request::getOverwriteHost(); - $this->assertNull($host); - - // clean up - unset($_SERVER['REMOTE_ADDR']); - OC_Config::deleteKey('overwritecondaddr'); - OC_Config::deleteKey('overwritehost'); - } - - public function hostWithPortProvider() { - return array( - array('localhost:500', 'localhost'), - array('foo.com', 'foo.com'), - array('[1fff:0:a88:85a3::ac1f]:801', '[1fff:0:a88:85a3::ac1f]'), - array('[1fff:0:a88:85a3::ac1f]', '[1fff:0:a88:85a3::ac1f]') - ); - } - - /** - * @dataProvider hostWithPortProvider - */ - public function testGetDomainWithoutPort($hostWithPort, $host) { - $this->assertEquals($host, OC_Request::getDomainWithoutPort($hostWithPort)); - - } - - /** - * @dataProvider trustedDomainDataProvider - */ - public function testIsTrustedDomain($trustedDomains, $testDomain, $result) { - OC_Config::deleteKey('trusted_domains'); - if ($trustedDomains !== null) { - OC_Config::setValue('trusted_domains', $trustedDomains); - } - - $this->assertEquals($result, OC_Request::isTrustedDomain($testDomain)); - - // clean up - OC_Config::deleteKey('trusted_domains'); - } - - public function trustedDomainDataProvider() { - $trustedHostTestList = array('host.one.test', 'host.two.test', '[1fff:0:a88:85a3::ac1f]'); - return array( - // empty defaults to true - array(null, 'host.one.test:8080', true), - array('', 'host.one.test:8080', true), - array(array(), 'host.one.test:8080', true), - - // trust list when defined - array($trustedHostTestList, 'host.two.test:8080', true), - array($trustedHostTestList, 'host.two.test:9999', true), - array($trustedHostTestList, 'host.three.test:8080', false), - array($trustedHostTestList, 'host.two.test:8080:aa:222', false), - array($trustedHostTestList, '[1fff:0:a88:85a3::ac1f]', true), - array($trustedHostTestList, '[1fff:0:a88:85a3::ac1f]:801', true), - array($trustedHostTestList, '[1fff:0:a88:85a3::ac1f]:801:34', false), - - // trust localhost regardless of trust list - array($trustedHostTestList, 'localhost', true), - array($trustedHostTestList, 'localhost:8080', true), - array($trustedHostTestList, '127.0.0.1', true), - array($trustedHostTestList, '127.0.0.1:8080', true), - - // do not trust invalid localhosts - array($trustedHostTestList, 'localhost:1:2', false), - array($trustedHostTestList, 'localhost: evil.host', false), - ); - } - - public function testServerHost() { - OC_Config::deleteKey('overwritecondaddr'); - OC_Config::setValue('overwritehost', 'overwritten.host:8080'); - OC_Config::setValue( - 'trusted_domains', - array( - 'trusted.host:8080', - 'second.trusted.host:8080' - ) - ); - $_SERVER['HTTP_HOST'] = 'trusted.host:8080'; - - // CLI always gives localhost - $oldCLI = OC::$CLI; - OC::$CLI = true; - $host = OC_Request::serverHost(); - $this->assertEquals('localhost', $host); - OC::$CLI = false; - - // overwritehost overrides trusted domain - $host = OC_Request::serverHost(); - $this->assertEquals('overwritten.host:8080', $host); - - // trusted domain returned when used - OC_Config::deleteKey('overwritehost'); - $host = OC_Request::serverHost(); - $this->assertEquals('trusted.host:8080', $host); - - // trusted domain returned when untrusted one in header - $_SERVER['HTTP_HOST'] = 'untrusted.host:8080'; - OC_Config::deleteKey('overwritehost'); - $host = OC_Request::serverHost(); - $this->assertEquals('trusted.host:8080', $host); - - // clean up - OC_Config::deleteKey('overwritecondaddr'); - OC_Config::deleteKey('overwritehost'); - unset($_SERVER['HTTP_HOST']); - OC::$CLI = $oldCLI; - } -} diff --git a/tests/lib/security/trusteddomainhelper.php b/tests/lib/security/trusteddomainhelper.php new file mode 100644 index 00000000000..c8d5ffa587b --- /dev/null +++ b/tests/lib/security/trusteddomainhelper.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright (c) 2015 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +use \OC\Security\TrustedDomainHelper; +use OCP\IConfig; + +/** + * Class TrustedDomainHelperTest + */ +class TrustedDomainHelperTest extends \Test\TestCase { + /** @var IConfig */ + protected $config; + + protected function setUp() { + parent::setUp(); + + $this->config = $this->getMockBuilder('\OCP\IConfig')->getMock(); + } + + /** + * @dataProvider trustedDomainDataProvider + * @param string $trustedDomains + * @param string $testDomain + * @param bool $result + */ + public function testIsTrustedDomain($trustedDomains, $testDomain, $result) { + $this->config->expects($this->once()) + ->method('getSystemValue') + ->with('trusted_domains') + ->will($this->returnValue($trustedDomains)); + + $trustedDomainHelper = new TrustedDomainHelper($this->config); + $this->assertEquals($result, $trustedDomainHelper->isTrustedDomain($testDomain)); + } + + /** + * @return array + */ + public function trustedDomainDataProvider() { + $trustedHostTestList = ['host.one.test', 'host.two.test', '[1fff:0:a88:85a3::ac1f]']; + return [ + // empty defaults to false with 8.1 + [null, 'host.one.test:8080', false], + ['', 'host.one.test:8080', false], + [[], 'host.one.test:8080', false], + // trust list when defined + [$trustedHostTestList, 'host.two.test:8080', true], + [$trustedHostTestList, 'host.two.test:9999', true], + [$trustedHostTestList, 'host.three.test:8080', false], + [$trustedHostTestList, 'host.two.test:8080:aa:222', false], + [$trustedHostTestList, '[1fff:0:a88:85a3::ac1f]', true], + [$trustedHostTestList, '[1fff:0:a88:85a3::ac1f]:801', true], + [$trustedHostTestList, '[1fff:0:a88:85a3::ac1f]:801:34', false], + // trust localhost regardless of trust list + [$trustedHostTestList, 'localhost', true], + [$trustedHostTestList, 'localhost:8080', true], + [$trustedHostTestList, '127.0.0.1', true], + [$trustedHostTestList, '127.0.0.1:8080', true], + // do not trust invalid localhosts + [$trustedHostTestList, 'localhost:1:2', false], + [$trustedHostTestList, 'localhost: evil.host', false], + ]; + } + +} diff --git a/tests/lib/setup.php b/tests/lib/setup.php index a221943c016..caaeec08fb3 100644 --- a/tests/lib/setup.php +++ b/tests/lib/setup.php @@ -10,16 +10,27 @@ use OCP\IConfig; class Test_OC_Setup extends \Test\TestCase { - /** @var IConfig */ + /** @var IConfig | PHPUnit_Framework_MockObject_MockObject */ protected $config; - /** @var \OC_Setup */ + /** @var \bantu\IniGetWrapper\IniGetWrapper | PHPUnit_Framework_MockObject_MockObject */ + private $iniWrapper; + /** @var \OCP\IL10N | PHPUnit_Framework_MockObject_MockObject */ + private $l10n; + /** @var \OC_Defaults | PHPUnit_Framework_MockObject_MockObject */ + private $defaults; + /** @var \OC\Setup | PHPUnit_Framework_MockObject_MockObject */ protected $setupClass; protected function setUp() { parent::setUp(); $this->config = $this->getMock('\OCP\IConfig'); - $this->setupClass = $this->getMock('\OC_Setup', ['class_exists', 'is_callable'], [$this->config]); + $this->iniWrapper = $this->getMock('\bantu\IniGetWrapper\IniGetWrapper'); + $this->l10n = $this->getMock('\OCP\IL10N'); + $this->defaults = $this->getMock('\OC_Defaults'); + $this->setupClass = $this->getMock('\OC\Setup', + ['class_exists', 'is_callable'], + [$this->config, $this->iniWrapper, $this->l10n, $this->defaults]); } public function testGetSupportedDatabasesWithOneWorking() { @@ -115,4 +126,4 @@ class Test_OC_Setup extends \Test\TestCase { ); $this->assertTrue($result); } -}
\ No newline at end of file +} diff --git a/tests/lib/share/share.php b/tests/lib/share/share.php index 6a50dd1f962..1ef62dc2b07 100644 --- a/tests/lib/share/share.php +++ b/tests/lib/share/share.php @@ -586,7 +586,10 @@ class Test_Share extends \Test\TestCase { // Attempt user specific target conflict OC_User::setUserId($this->user3); + \OCP\Util::connectHook('OCP\\Share', 'post_shared', 'DummyHookListener', 'listen'); + $this->assertTrue(OCP\Share::shareItem('test', 'share.txt', OCP\Share::SHARE_TYPE_GROUP, $this->group1, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_SHARE)); + $this->assertEquals(OCP\Share::SHARE_TYPE_GROUP, DummyHookListener::$shareType); OC_User::setUserId($this->user2); $to_test = OCP\Share::getItemsSharedWith('test', Test_Share_Backend::FORMAT_TARGET); $this->assertEquals(2, count($to_test)); @@ -1055,3 +1058,11 @@ class DummyShareClass extends \OC\Share\Share { return parent::groupItems($items, 'test'); } } + +class DummyHookListener { + static $shareType = null; + + public static function listen($params) { + self::$shareType = $params['shareType']; + } +} diff --git a/tests/lib/tags.php b/tests/lib/tags.php index 547cd302d5d..1a13d64679d 100644 --- a/tests/lib/tags.php +++ b/tests/lib/tags.php @@ -49,7 +49,7 @@ class Test_Tags extends \Test\TestCase { ->will($this->returnValue($this->user)); $this->objectType = $this->getUniqueID('type_'); - $this->tagMapper = new OC\Tagging\TagMapper(\OC::$server->getDb()); + $this->tagMapper = new OC\Tagging\TagMapper(\OC::$server->getDatabaseConnection()); $this->tagMgr = new OC\TagManager($this->tagMapper, $this->userSession); } @@ -62,6 +62,16 @@ class Test_Tags extends \Test\TestCase { parent::tearDown(); } + public function testTagManagerWithoutUserReturnsNull() { + $this->userSession = $this->getMock('\OCP\IUserSession'); + $this->userSession + ->expects($this->any()) + ->method('getUser') + ->will($this->returnValue(null)); + $this->tagMgr = new OC\TagManager($this->tagMapper, $this->userSession); + $this->assertNull($this->tagMgr->load($this->objectType)); + } + public function testInstantiateWithDefaults() { $defaultTags = array('Friends', 'Family', 'Work', 'Other'); diff --git a/tests/lib/template/resourcelocator.php b/tests/lib/template/resourcelocator.php index f350fd144e1..b0851621fd2 100644 --- a/tests/lib/template/resourcelocator.php +++ b/tests/lib/template/resourcelocator.php @@ -7,13 +7,20 @@ */ class Test_ResourceLocator extends \Test\TestCase { + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $logger; + + protected function setUp() { + parent::setUp(); + $this->logger = $this->getMock('OCP\ILogger'); + } /** * @param string $theme */ public function getResourceLocator( $theme, $core_map, $party_map, $appsroots ) { return $this->getMockForAbstractClass('OC\Template\ResourceLocator', - array( $theme, $core_map, $party_map, $appsroots ), + array($this->logger, $theme, $core_map, $party_map, $appsroots ), '', true, true, true, array()); } @@ -30,7 +37,7 @@ class Test_ResourceLocator extends \Test\TestCase { public function testFind() { $locator = $this->getResourceLocator('theme', - array('core'=>'map'), array('3rd'=>'party'), array('foo'=>'bar')); + array('core' => 'map'), array('3rd' => 'party'), array('foo' => 'bar')); $locator->expects($this->once()) ->method('doFind') ->with('foo'); @@ -38,18 +45,22 @@ class Test_ResourceLocator extends \Test\TestCase { ->method('doFindTheme') ->with('foo'); $locator->find(array('foo')); + } + public function testFindNotFound() { $locator = $this->getResourceLocator('theme', array('core'=>'map'), array('3rd'=>'party'), array('foo'=>'bar')); $locator->expects($this->once()) ->method('doFind') ->with('foo') - ->will($this->throwException(new Exception('test'))); - try { - $locator->find(array('foo')); - } catch (\Exception $e) { - $this->assertEquals('test serverroot:core', $e->getMessage()); - } + ->will($this->throwException(new \OC\Template\ResourceNotFoundException('foo', 'map'))); + $locator->expects($this->once()) + ->method('doFindTheme') + ->with('foo') + ->will($this->throwException(new \OC\Template\ResourceNotFoundException('foo', 'map'))); + $this->logger->expects($this->exactly(2)) + ->method('error'); + $locator->find(array('foo')); } public function testAppendIfExist() { diff --git a/tests/lib/templatelayout.php b/tests/lib/templatelayout.php deleted file mode 100644 index 1035dae122d..00000000000 --- a/tests/lib/templatelayout.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php -/** - * Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -namespace OC\Test; - -/** - * @package OC\Test - */ -class OC_TemplateLayout extends \Test\TestCase { - - private $oldServerURI; - private $oldScriptName; - - protected function setUp() { - parent::setUp(); - - $this->oldServerURI = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null; - $this->oldScriptName = $_SERVER['SCRIPT_NAME']; - } - - protected function tearDown() { - if ($this->oldServerURI === null) { - unset($_SERVER['REQUEST_URI']); - } else { - $_SERVER['REQUEST_URI'] = $this->oldServerURI; - } - $_SERVER['SCRIPT_NAME'] = $this->oldScriptName; - - parent::tearDown(); - } - - /** - * Contains valid file paths in the scheme array($absolutePath, $expectedPath) - * @return array - */ - public function validFilePathProvider() { - return array( - array(\OC::$SERVERROOT . '/apps/files/js/fancyJS.js', '/apps/files/js/fancyJS.js'), - array(\OC::$SERVERROOT. '/test.js', '/test.js'), - array(\OC::$SERVERROOT . '/core/test.js', '/core/test.js'), - array(\OC::$SERVERROOT, ''), - ); - } - - /** - * @dataProvider validFilePathProvider - */ - public function testConvertToRelativePath($absolutePath, $expected) { - $_SERVER['REQUEST_URI'] = $expected; - $_SERVER['SCRIPT_NAME'] = '/'; - - $relativePath = \Test_Helper::invokePrivate(new \OC_TemplateLayout('user'), 'convertToRelativePath', array($absolutePath)); - $this->assertEquals($expected, $relativePath); - } - - /** - * @expectedException \Exception - * @expectedExceptionMessage $filePath is not under the \OC::$SERVERROOT - */ - public function testInvalidConvertToRelativePath() { - $invalidFile = '/this/file/is/invalid'; - $_SERVER['REQUEST_URI'] = $invalidFile; - $_SERVER['SCRIPT_NAME'] = '/'; - - \Test_Helper::invokePrivate(new \OC_TemplateLayout('user'), 'convertToRelativePath', array($invalidFile)); - } -} diff --git a/tests/lib/updater.php b/tests/lib/updater.php index f847ffc91bf..7a1bc48e1a8 100644 --- a/tests/lib/updater.php +++ b/tests/lib/updater.php @@ -88,7 +88,7 @@ class UpdaterTest extends \Test\TestCase { protected function getUpdaterMock($content){ // Invalidate cache - $mockedAppConfig = $this->getMockBuilder('\OC\AppConfig') + $mockedConfig = $this->getMockBuilder('\OCP\IConfig') ->disableOriginalConstructor() ->getMock() ; @@ -101,7 +101,7 @@ class UpdaterTest extends \Test\TestCase { $mockedHTTPHelper->expects($this->once())->method('getUrlContent')->will($this->returnValue($content)); - return new Updater($mockedHTTPHelper, $mockedAppConfig); + return new Updater($mockedHTTPHelper, $mockedConfig); } } diff --git a/tests/lib/util.php b/tests/lib/util.php index 25c9e31beaf..a852eee8ad6 100644 --- a/tests/lib/util.php +++ b/tests/lib/util.php @@ -1,11 +1,11 @@ <?php + /** * Copyright (c) 2012 Lukas Reschke <lukas@statuscode.ch> * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. */ - class Test_Util extends \Test\TestCase { public function testGetVersion() { $version = \OC_Util::getVersion(); @@ -52,16 +52,31 @@ class Test_Util extends \Test\TestCase { OC_Util::formatDate(1350129205, false, 'Mordor/Barad-dûr'); } - function testFormatDateWithTZFromSession() { + public function formatDateWithTZFromSessionData() + { + return array( + array(3, 'October 13, 2012 at 2:53:25 PM GMT+3'), + array(15, 'October 13, 2012 at 11:53:25 AM GMT+0'), + array(-13, 'October 13, 2012 at 11:53:25 AM GMT+0'), + array(3.5, 'October 13, 2012 at 3:23:25 PM GMT+3:30'), + array(9.5, 'October 13, 2012 at 9:23:25 PM GMT+9:30'), + array(-4.5, 'October 13, 2012 at 7:23:25 AM GMT-4:30'), + array(15.5, 'October 13, 2012 at 11:53:25 AM GMT+0'), + ); + } + + /** + * @dataProvider formatDateWithTZFromSessionData + */ + function testFormatDateWithTZFromSession($offset, $expected) { date_default_timezone_set("UTC"); $oldDateTimeFormatter = \OC::$server->query('DateTimeFormatter'); - \OC::$server->getSession()->set('timezone', 3); + \OC::$server->getSession()->set('timezone', $offset); $newDateTimeFormatter = new \OC\DateTimeFormatter(\OC::$server->getDateTimeZone()->getTimeZone(), new \OC_L10N('lib', 'en')); $this->setDateFormatter($newDateTimeFormatter); $result = OC_Util::formatDate(1350129205, false); - $expected = 'October 13, 2012 at 2:53:25 PM GMT+3'; $this->assertEquals($expected, $result); $this->setDateFormatter($oldDateTimeFormatter); @@ -105,7 +120,7 @@ class Test_Util extends \Test\TestCase { $this->assertEquals('This is a good string without HTML.', $result); } - function testEncodePath(){ + function testEncodePath() { $component = '/§#@test%&^ä/-child'; $result = OC_Util::encodePath($component); $this->assertEquals("/%C2%A7%23%40test%25%26%5E%C3%A4/-child", $result); @@ -210,14 +225,12 @@ class Test_Util extends \Test\TestCase { /** * @dataProvider baseNameProvider */ - public function testBaseName($expected, $file) - { + public function testBaseName($expected, $file) { $base = \OC_Util::basename($file); $this->assertEquals($expected, $base); } - public function baseNameProvider() - { + public function baseNameProvider() { return array( array('public_html', '/home/user/public_html/'), array('public_html', '/home/user/public_html'), @@ -288,11 +301,11 @@ class Test_Util extends \Test\TestCase { \OC_User::createUser($uid, "passwd"); - foreach($groups as $group) { + foreach ($groups as $group) { \OC_Group::createGroup($group); } - foreach($membership as $group) { + foreach ($membership as $group) { \OC_Group::addToGroup($uid, $group); } @@ -308,7 +321,7 @@ class Test_Util extends \Test\TestCase { \OC_User::deleteUser($uid); \OC_User::setUserId(''); - foreach($groups as $group) { + foreach ($groups as $group) { \OC_Group::deleteGroup($group); } @@ -317,7 +330,7 @@ class Test_Util extends \Test\TestCase { } - public function dataProviderForTestIsSharingDisabledForUser() { + public function dataProviderForTestIsSharingDisabledForUser() { return array( // existing groups, groups the user belong to, groups excluded from sharing, expected result array(array('g1', 'g2', 'g3'), array(), array('g1'), false), @@ -327,8 +340,8 @@ class Test_Util extends \Test\TestCase { array(array('g1', 'g2', 'g3'), array('g1', 'g2'), array('g1'), false), array(array('g1', 'g2', 'g3'), array('g1', 'g2'), array('g1', 'g2'), true), array(array('g1', 'g2', 'g3'), array('g1', 'g2'), array('g1', 'g2', 'g3'), true), - ); - } + ); + } /** * Test default apps @@ -341,15 +354,21 @@ class Test_Util extends \Test\TestCase { $oldWebRoot = \OC::$WEBROOT; \OC::$WEBROOT = ''; - Dummy_OC_App::setEnabledApps($enabledApps); + $appManager = $this->getMock('\OCP\App\IAppManager'); + $appManager->expects($this->any()) + ->method('isEnabledForUser') + ->will($this->returnCallback(function($appId) use ($enabledApps){ + return in_array($appId, $enabledApps); + })); + Dummy_OC_Util::$appManager = $appManager; + // need to set a user id to make sure enabled apps are read from cache \OC_User::setUserId($this->getUniqueID()); \OCP\Config::setSystemValue('defaultapp', $defaultAppConfig); - $this->assertEquals('http://localhost/' . $expectedPath, \OC_Util::getDefaultPageUrl()); + $this->assertEquals('http://localhost/' . $expectedPath, Dummy_OC_Util::getDefaultPageUrl()); // restore old state \OC::$WEBROOT = $oldWebRoot; - Dummy_OC_App::restore(); \OCP\Config::setSystemValue('defaultapp', $oldDefaultApps); \OC_User::setUserId(null); } @@ -405,18 +424,15 @@ class Test_Util extends \Test\TestCase { } /** - * Dummy OC Apps class to make it possible to override - * enabled apps + * Dummy OC Util class to make it possible to override the app manager */ -class Dummy_OC_App extends OC_App { - private static $enabledAppsCacheBackup; - - public static function setEnabledApps($enabledApps) { - self::$enabledAppsCacheBackup = self::$enabledAppsCache; - self::$enabledAppsCache = $enabledApps; - } +class Dummy_OC_Util extends OC_Util { + /** + * @var \OCP\App\IAppManager + */ + public static $appManager; - public static function restore() { - self::$enabledAppsCache = self::$enabledAppsCacheBackup; + protected static function getAppManager() { + return self::$appManager; } } diff --git a/tests/lib/vobject.php b/tests/lib/vobject.php deleted file mode 100644 index 6fabf30e48f..00000000000 --- a/tests/lib/vobject.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php -/** - * Copyright (c) 2013 Thomas Tanghus (thomas@tanghus.net) - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -class Test_VObject extends \Test\TestCase { - - protected function setUp() { - parent::setUp(); - - Sabre\VObject\Property::$classMap['SUMMARY'] = 'OC\VObject\StringProperty'; - Sabre\VObject\Property::$classMap['ORG'] = 'OC\VObject\CompoundProperty'; - } - - function testStringProperty() { - $property = Sabre\VObject\Property::create('SUMMARY', 'Escape;this,please'); - $this->assertEquals("SUMMARY:Escape\;this\,please\r\n", $property->serialize()); - } - - function testCompoundProperty() { - - $arr = array( - 'ABC, Inc.', - 'North American Division', - 'Marketing;Sales', - ); - - $property = Sabre\VObject\Property::create('ORG'); - $property->setParts($arr); - - $this->assertEquals('ABC\, Inc.;North American Division;Marketing\;Sales', $property->value); - $this->assertEquals('ORG:ABC\, Inc.;North American Division;Marketing\;Sales' . "\r\n", $property->serialize()); - $this->assertEquals(3, count($property->getParts())); - $parts = $property->getParts(); - $this->assertEquals('Marketing;Sales', $parts[2]); - } -} |