diff options
Diffstat (limited to 'tests/lib/Files/FilesystemTest.php')
-rw-r--r-- | tests/lib/Files/FilesystemTest.php | 490 |
1 files changed, 490 insertions, 0 deletions
diff --git a/tests/lib/Files/FilesystemTest.php b/tests/lib/Files/FilesystemTest.php new file mode 100644 index 00000000000..a4a4345d2f9 --- /dev/null +++ b/tests/lib/Files/FilesystemTest.php @@ -0,0 +1,490 @@ +<?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\Files; + +use OC\Files\Mount\MountPoint; +use OC\Files\Storage\Temporary; +use OC\User\NoUserException; +use OCP\Files\Config\IMountProvider; +use OCP\Files\Storage\IStorageFactory; +use OCP\IUser; + +class DummyMountProvider implements IMountProvider { + private $mounts = []; + + /** + * @param array $mounts + */ + public function __construct(array $mounts) { + $this->mounts = $mounts; + } + + /** + * Get the pre-registered mount points + * + * @param IUser $user + * @param IStorageFactory $loader + * @return \OCP\Files\Mount\IMountPoint[] + */ + public function getMountsForUser(IUser $user, IStorageFactory $loader) { + return isset($this->mounts[$user->getUID()]) ? $this->mounts[$user->getUID()] : []; + } +} + +/** + * Class FilesystemTest + * + * @group DB + * + * @package Test\Files + */ +class FilesystemTest extends \Test\TestCase { + + const TEST_FILESYSTEM_USER1 = "test-filesystem-user1"; + const TEST_FILESYSTEM_USER2 = "test-filesystem-user1"; + + /** + * @var array tmpDirs + */ + private $tmpDirs = array(); + + /** + * @return array + */ + private function getStorageData() { + $dir = \OC::$server->getTempManager()->getTemporaryFolder(); + $this->tmpDirs[] = $dir; + return array('datadir' => $dir); + } + + protected function setUp() { + parent::setUp(); + $userBackend = new \Test\Util\User\Dummy(); + $userBackend->createUser(self::TEST_FILESYSTEM_USER1, self::TEST_FILESYSTEM_USER1); + $userBackend->createUser(self::TEST_FILESYSTEM_USER2, self::TEST_FILESYSTEM_USER2); + \OC::$server->getUserManager()->registerBackend($userBackend); + $this->loginAsUser(); + } + + protected function tearDown() { + foreach ($this->tmpDirs as $dir) { + \OC_Helper::rmdirr($dir); + } + + $this->logout(); + parent::tearDown(); + } + + public function testMount() { + \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', self::getStorageData(), '/'); + $this->assertEquals('/', \OC\Files\Filesystem::getMountPoint('/')); + $this->assertEquals('/', \OC\Files\Filesystem::getMountPoint('/some/folder')); + list(, $internalPath) = \OC\Files\Filesystem::resolvePath('/'); + $this->assertEquals('', $internalPath); + list(, $internalPath) = \OC\Files\Filesystem::resolvePath('/some/folder'); + $this->assertEquals('some/folder', $internalPath); + + \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', self::getStorageData(), '/some'); + $this->assertEquals('/', \OC\Files\Filesystem::getMountPoint('/')); + $this->assertEquals('/some/', \OC\Files\Filesystem::getMountPoint('/some/folder')); + $this->assertEquals('/some/', \OC\Files\Filesystem::getMountPoint('/some/')); + $this->assertEquals('/some/', \OC\Files\Filesystem::getMountPoint('/some')); + list(, $internalPath) = \OC\Files\Filesystem::resolvePath('/some/folder'); + $this->assertEquals('folder', $internalPath); + } + + public function normalizePathData() { + return array( + array('/', ''), + array('/', '/'), + array('/', '//'), + array('/', '/', false), + array('/', '//', false), + + array('/path', '/path/'), + array('/path/', '/path/', false), + array('/path', 'path'), + + array('/foo/bar', '/foo//bar/'), + array('/foo/bar/', '/foo//bar/', false), + array('/foo/bar', '/foo////bar'), + array('/foo/bar', '/foo/////bar'), + array('/foo/bar', '/foo/bar/.'), + array('/foo/bar', '/foo/bar/./'), + array('/foo/bar/', '/foo/bar/./', false), + array('/foo/bar', '/foo/bar/./.'), + array('/foo/bar', '/foo/bar/././'), + array('/foo/bar/', '/foo/bar/././', false), + array('/foo/bar', '/foo/./bar/'), + array('/foo/bar/', '/foo/./bar/', false), + array('/foo/.bar', '/foo/.bar/'), + array('/foo/.bar/', '/foo/.bar/', false), + array('/foo/.bar/tee', '/foo/.bar/tee'), + + // Windows paths + array('/', ''), + array('/', '\\'), + array('/', '\\', false), + array('/', '\\\\'), + array('/', '\\\\', false), + + array('/path', '\\path'), + array('/path', '\\path', false), + array('/path', '\\path\\'), + array('/path/', '\\path\\', false), + + array('/foo/bar', '\\foo\\\\bar\\'), + array('/foo/bar/', '\\foo\\\\bar\\', false), + array('/foo/bar', '\\foo\\\\\\\\bar'), + array('/foo/bar', '\\foo\\\\\\\\\\bar'), + array('/foo/bar', '\\foo\\bar\\.'), + array('/foo/bar', '\\foo\\bar\\.\\'), + array('/foo/bar/', '\\foo\\bar\\.\\', false), + array('/foo/bar', '\\foo\\bar\\.\\.'), + array('/foo/bar', '\\foo\\bar\\.\\.\\'), + array('/foo/bar/', '\\foo\\bar\\.\\.\\', false), + array('/foo/bar', '\\foo\\.\\bar\\'), + array('/foo/bar/', '\\foo\\.\\bar\\', false), + array('/foo/.bar', '\\foo\\.bar\\'), + array('/foo/.bar/', '\\foo\\.bar\\', false), + array('/foo/.bar/tee', '\\foo\\.bar\\tee'), + + // Absolute windows paths NOT marked as absolute + array('/C:', 'C:\\'), + array('/C:/', 'C:\\', false), + array('/C:/tests', 'C:\\tests'), + array('/C:/tests', 'C:\\tests', false), + array('/C:/tests', 'C:\\tests\\'), + array('/C:/tests/', 'C:\\tests\\', false), + + // normalize does not resolve '..' (by design) + array('/foo/..', '/foo/../'), + array('/foo/..', '\\foo\\..\\'), + ); + } + + /** + * @dataProvider normalizePathData + */ + public function testNormalizePath($expected, $path, $stripTrailingSlash = true) { + $this->assertEquals($expected, \OC\Files\Filesystem::normalizePath($path, $stripTrailingSlash)); + } + + public function isValidPathData() { + return array( + array('/', true), + array('/path', true), + array('/foo/bar', true), + array('/foo//bar/', true), + array('/foo////bar', true), + array('/foo//\///bar', true), + array('/foo/bar/.', true), + array('/foo/bar/./', true), + array('/foo/bar/./.', true), + array('/foo/bar/././', true), + array('/foo/bar/././..bar', true), + array('/foo/bar/././..bar/a', true), + array('/foo/bar/././..', false), + array('/foo/bar/././../', false), + array('/foo/bar/.././', false), + array('/foo/bar/../../', false), + array('/foo/bar/../..\\', false), + array('..', false), + array('../', false), + array('../foo/bar', false), + array('..\foo/bar', false), + ); + } + + /** + * @dataProvider isValidPathData + */ + public function testIsValidPath($path, $expected) { + $this->assertSame($expected, \OC\Files\Filesystem::isValidPath($path)); + } + + public function isFileBlacklistedData() { + return array( + array('/etc/foo/bar/foo.txt', false), + array('\etc\foo/bar\foo.txt', false), + array('.htaccess', true), + array('.htaccess/', true), + array('.htaccess\\', true), + array('/etc/foo\bar/.htaccess\\', true), + array('/etc/foo\bar/.htaccess/', true), + array('/etc/foo\bar/.htaccess/foo', false), + array('//foo//bar/\.htaccess/', true), + array('\foo\bar\.HTAccess', true), + ); + } + + /** + * @dataProvider isFileBlacklistedData + */ + public function testIsFileBlacklisted($path, $expected) { + $this->assertSame($expected, \OC\Files\Filesystem::isFileBlacklisted($path)); + } + + public function normalizePathWindowsAbsolutePathData() { + return array( + array('C:/', 'C:\\'), + array('C:/', 'C:\\', false), + array('C:/tests', 'C:\\tests'), + array('C:/tests', 'C:\\tests', false), + array('C:/tests', 'C:\\tests\\'), + array('C:/tests/', 'C:\\tests\\', false), + ); + } + + /** + * @dataProvider normalizePathWindowsAbsolutePathData + */ + public function testNormalizePathWindowsAbsolutePath($expected, $path, $stripTrailingSlash = true) { + if (!\OC_Util::runningOnWindows()) { + $this->markTestSkipped('This test is Windows only'); + } + + $this->assertEquals($expected, \OC\Files\Filesystem::normalizePath($path, $stripTrailingSlash, true)); + } + + public function testNormalizePathUTF8() { + if (!class_exists('Patchwork\PHP\Shim\Normalizer')) { + $this->markTestSkipped('UTF8 normalizer Patchwork was not found'); + } + + $this->assertEquals("/foo/bar\xC3\xBC", \OC\Files\Filesystem::normalizePath("/foo/baru\xCC\x88")); + $this->assertEquals("/foo/bar\xC3\xBC", \OC\Files\Filesystem::normalizePath("\\foo\\baru\xCC\x88")); + } + + public function testHooks() { + if (\OC\Files\Filesystem::getView()) { + $user = \OC_User::getUser(); + } else { + $user = self::TEST_FILESYSTEM_USER1; + $backend = new \Test\Util\User\Dummy(); + \OC_User::useBackend($backend); + $backend->createUser($user, $user); + $userObj = \OC::$server->getUserManager()->get($user); + \OC::$server->getUserSession()->setUser($userObj); + \OC\Files\Filesystem::init($user, '/' . $user . '/files'); + + } + \OC_Hook::clear('OC_Filesystem'); + \OC_Hook::connect('OC_Filesystem', 'post_write', $this, 'dummyHook'); + + \OC\Files\Filesystem::mount('OC\Files\Storage\Temporary', array(), '/'); + + $rootView = new \OC\Files\View(''); + $rootView->mkdir('/' . $user); + $rootView->mkdir('/' . $user . '/files'); + +// \OC\Files\Filesystem::file_put_contents('/foo', 'foo'); + \OC\Files\Filesystem::mkdir('/bar'); +// \OC\Files\Filesystem::file_put_contents('/bar//foo', 'foo'); + + $tmpFile = \OC::$server->getTempManager()->getTemporaryFile(); + file_put_contents($tmpFile, 'foo'); + $fh = fopen($tmpFile, 'r'); +// \OC\Files\Filesystem::file_put_contents('/bar//foo', $fh); + } + + /** + * Tests that an exception is thrown when passed user does not exist. + * + * @expectedException \OC\User\NoUserException + */ + public function testLocalMountWhenUserDoesNotExist() { + $userId = $this->getUniqueID('user_'); + + \OC\Files\Filesystem::initMountPoints($userId); + } + + /** + * @expectedException \OC\User\NoUserException + */ + public function testNullUserThrows() { + \OC\Files\Filesystem::initMountPoints(null); + } + + public function testNullUserThrowsTwice() { + $thrown = 0; + try { + \OC\Files\Filesystem::initMountPoints(null); + } catch (NoUserException $e) { + $thrown++; + } + try { + \OC\Files\Filesystem::initMountPoints(null); + } catch (NoUserException $e) { + $thrown++; + } + $this->assertEquals(2, $thrown); + } + + /** + * Tests that an exception is thrown when passed user does not exist. + */ + public function testLocalMountWhenUserDoesNotExistTwice() { + $thrown = 0; + $userId = $this->getUniqueID('user_'); + + try { + \OC\Files\Filesystem::initMountPoints($userId); + } catch (NoUserException $e) { + $thrown++; + } + + try { + \OC\Files\Filesystem::initMountPoints($userId); + } catch (NoUserException $e) { + $thrown++; + } + + $this->assertEquals(2, $thrown); + } + + /** + * Tests that the home storage is used for the user's mount point + */ + public function testHomeMount() { + $userId = $this->getUniqueID('user_'); + + \OC::$server->getUserManager()->createUser($userId, $userId); + + \OC\Files\Filesystem::initMountPoints($userId); + + $homeMount = \OC\Files\Filesystem::getStorage('/' . $userId . '/'); + + $this->assertTrue($homeMount->instanceOfStorage('\OCP\Files\IHomeStorage')); + if (getenv('RUN_OBJECTSTORE_TESTS')) { + $this->assertTrue($homeMount->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage')); + $this->assertEquals('object::user:' . $userId, $homeMount->getId()); + } else { + $this->assertTrue($homeMount->instanceOfStorage('\OC\Files\Storage\Home')); + $this->assertEquals('home::' . $userId, $homeMount->getId()); + } + + $user = \OC::$server->getUserManager()->get($userId); + if ($user !== null) { $user->delete(); } + } + + /** + * Tests that the home storage is used in legacy mode + * for the user's mount point + */ + public function testLegacyHomeMount() { + if (getenv('RUN_OBJECTSTORE_TESTS')) { + $this->markTestSkipped('legacy storage unrelated to objectstore environments'); + } + $datadir = \OC::$server->getConfig()->getSystemValue("datadirectory", \OC::$SERVERROOT . "/data"); + $userId = $this->getUniqueID('user_'); + + // insert storage into DB by constructing it + // to make initMountsPoint find its existence + $localStorage = new \OC\Files\Storage\Local(array('datadir' => $datadir . '/' . $userId . '/')); + // this will trigger the insert + $cache = $localStorage->getCache(); + + \OC::$server->getUserManager()->createUser($userId, $userId); + \OC\Files\Filesystem::initMountPoints($userId); + + $homeMount = \OC\Files\Filesystem::getStorage('/' . $userId . '/'); + + $this->assertTrue($homeMount->instanceOfStorage('\OC\Files\Storage\Home')); + $this->assertEquals('local::' . $datadir . '/' . $userId . '/', $homeMount->getId()); + + $user = \OC::$server->getUserManager()->get($userId); + if ($user !== null) { $user->delete(); } + // delete storage entry + $cache->clear(); + } + + public function dummyHook($arguments) { + $path = $arguments['path']; + $this->assertEquals($path, \OC\Files\Filesystem::normalizePath($path)); //the path passed to the hook should already be normalized + } + + /** + * Test that the default cache dir is part of the user's home + */ + public function testMountDefaultCacheDir() { + $userId = $this->getUniqueID('user_'); + $config = \OC::$server->getConfig(); + $oldCachePath = $config->getSystemValue('cache_path', ''); + // no cache path configured + $config->setSystemValue('cache_path', ''); + + \OC::$server->getUserManager()->createUser($userId, $userId); + \OC\Files\Filesystem::initMountPoints($userId); + + $this->assertEquals( + '/' . $userId . '/', + \OC\Files\Filesystem::getMountPoint('/' . $userId . '/cache') + ); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath('/' . $userId . '/cache'); + $this->assertTrue($storage->instanceOfStorage('\OCP\Files\IHomeStorage')); + $this->assertEquals('cache', $internalPath); + $user = \OC::$server->getUserManager()->get($userId); + if ($user !== null) { $user->delete(); } + + $config->setSystemValue('cache_path', $oldCachePath); + } + + /** + * Test that an external cache is mounted into + * the user's home + */ + public function testMountExternalCacheDir() { + $userId = $this->getUniqueID('user_'); + + $config = \OC::$server->getConfig(); + $oldCachePath = $config->getSystemValue('cache_path', ''); + // set cache path to temp dir + $cachePath = \OC::$server->getTempManager()->getTemporaryFolder() . '/extcache'; + $config->setSystemValue('cache_path', $cachePath); + + \OC::$server->getUserManager()->createUser($userId, $userId); + \OC\Files\Filesystem::initMountPoints($userId); + + $this->assertEquals( + '/' . $userId . '/cache/', + \OC\Files\Filesystem::getMountPoint('/' . $userId . '/cache') + ); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath('/' . $userId . '/cache'); + $this->assertTrue($storage->instanceOfStorage('\OC\Files\Storage\Local')); + $this->assertEquals('', $internalPath); + $user = \OC::$server->getUserManager()->get($userId); + if ($user !== null) { $user->delete(); } + + $config->setSystemValue('cache_path', $oldCachePath); + } + + public function testRegisterMountProviderAfterSetup() { + \OC\Files\Filesystem::initMountPoints(self::TEST_FILESYSTEM_USER2); + $this->assertEquals('/', \OC\Files\Filesystem::getMountPoint('/foo/bar')); + $mount = new MountPoint(new Temporary([]), '/foo/bar'); + $mountProvider = new DummyMountProvider([self::TEST_FILESYSTEM_USER2 => [$mount]]); + \OC::$server->getMountProviderCollection()->registerProvider($mountProvider); + $this->assertEquals('/foo/bar/', \OC\Files\Filesystem::getMountPoint('/foo/bar')); + } +} |