diff --git a/api/tests/Vfs/SharingTest.php b/api/tests/Vfs/SharingTest.php index 6a06f6f485..f4cf198e38 100644 --- a/api/tests/Vfs/SharingTest.php +++ b/api/tests/Vfs/SharingTest.php @@ -18,17 +18,30 @@ namespace EGroupware\Api\Vfs; use EGroupware\Api; use EGroupware\Api\Vfs; use EGroupware\Api\LoggedInTest as LoggedInTest; +use EGroupware\Stylite\Vfs\Versioning; class SharingTest extends LoggedInTest { - // Keep track of shares to remove after + /** + * Keep track of shares to remove after + */ protected $shares = Array(); - // Keep track of files to remove after + /** + * Keep track of files to remove after + * @var Array + */ protected $files = Array(); + /** + * Options for searching the Vfs (Vfs::find()) + */ + const VFS_OPTIONS = array( + 'maxdepth' => 5 + ); + public function setUp() { @@ -48,12 +61,11 @@ class SharingTest extends LoggedInTest // Need to ask about mounts, or other tests fail Vfs::mount(); - // Remove any added files - foreach($this->files as $path) - { - //echo "Unlinking $path: " . (Vfs::unlink($path) ? 'success' : 'failed'); - Vfs::unlink($path); - } + // Remove any added files as root to avoid versioning issues + $backup = Vfs::$is_root; + Vfs::$is_root = true; + Vfs::remove($this->files); + Vfs::$is_root = $backup; // Remove any added shares foreach($this->shares as $share) @@ -71,24 +83,7 @@ class SharingTest extends LoggedInTest { $dir = Vfs::get_home_dir().'/'; - //var_dump(Vfs::find('/',array('maxdepth' => 1))); - $logged_in_files = array_map( - function($path) use ($dir) {return str_replace($dir, '/', $path);}, - Vfs::find($dir) - ); - $this->shareLink($dir, Sharing::READONLY); - - $files = Vfs::find(Vfs::get_home_dir()); - - //var_dump(Vfs::find('/test_subdir',array('maxdepth' => 1))); - // Make sure files are the same - $this->assertEquals($logged_in_files, $files); - - // Make sure all are readonly - foreach($files as $file) - { - $this->assertFalse(Vfs::is_writable($file)); - } + $this->checkDirectory($dir, Sharing::WRITABLE); } /** @@ -99,42 +94,175 @@ class SharingTest extends LoggedInTest { $dir = Vfs::get_home_dir().'/'; - if(!Vfs::is_writable($dir)) + $this->checkDirectory($dir, Sharing::WRITABLE); + } + + /** + * Test for a readonly share of a path with versioning turned on + */ + public function testVersioningReadonly() + { + $this->files[] = $dir = Vfs::get_home_dir().'/versioned/'; + + // Create versioned directory + if(Vfs::is_dir($dir)) Vfs::remove($dir); + Vfs::mkdir($dir); + $this->assertTrue(Vfs::is_writable($dir), "Unable to write to '$dir' as expected"); + $this->mountVersioned($dir); + + $this->checkDirectory($dir, Sharing::READONLY); + } + + /** + * Test for a writable share of a path with versioning turned on + */ + public function testVersioningWritable() + { + $this->files[] = $dir = Vfs::get_home_dir().'/versioned/'; + + // Create versioned directory + if(Vfs::is_dir($dir)) Vfs::remove($dir); + Vfs::mkdir($dir); + $this->assertTrue(Vfs::is_writable($dir), "Unable to write to '$dir' as expected"); + $this->mountVersioned($dir); + + $this->checkDirectory($dir, Sharing::WRITABLE); + } + + /** + * Check a given directory to see that a link to it works. + * + * We check + * - Files/directories available to original user are available through share + * - Permissions match share (Read / Write) + * - Files are not empty + * + * @param string $dir + * @param string $mode + */ + protected function checkDirectory($dir, $mode) + { + $this->files += $this->addFiles($dir); + + $logged_in_files = array_map( + function($path) use ($dir) {return str_replace($dir, '/', $path);}, + Vfs::find($dir, static::VFS_OPTIONS) + ); + + //echo "\n".$this->getName(); + //echo "\nLogged in files:\n".implode("\n", $logged_in_files)."\n"; + + // Create and use link + $extra = array(); + switch($mode) { - $this->markTestSkipped("Unable to write to '$dir' as expected"); + case Sharing::WRITABLE: + $extra['share_writable'] = TRUE; + break; + } + $this->shareLink($dir, $mode, $extra); + + $files = Vfs::find('/', static::VFS_OPTIONS); + + //echo "\nLinked files:\n".implode("\n", $files)."\n"; + + // Make sure files are the same + $this->assertEquals($logged_in_files, $files); + + // Make sure all are readonly + foreach($files as $file) + { + $this->checkOneFile($file, $mode); + } + } + + /** + * Check the access permissions for one file/directory + * + * @param string $file + * @param string $mode + */ + protected function checkOneFile($file, $mode) + { + // All the test files have something in them + if(!Vfs::is_dir($file)) + { + $this->assertNotEmpty(file_get_contents(Vfs::PREFIX.$file), "$file was empty"); } - // Add some things for us to find, and make sure the dir is actually writable - $file = $dir.'test_file.txt'; - $this->files[] = $file; + // Check permissions + switch($mode) + { + case Sharing::READONLY: + $this->assertFalse(Vfs::is_writable($file)); + if(!Vfs::is_dir($file)) + { + $this->assertFalse(file_put_contents(Vfs::PREFIX.$file, 'Writable check')); + } + break; + case Sharing::WRITABLE: + // Root is not writable + if($file == '/') continue; + + $this->assertTrue(Vfs::is_writable($file), $file . ' was not writable'); + if(!Vfs::is_dir($file)) + { + $this->assertNotFalse(file_put_contents(Vfs::PREFIX.$file, 'Writable check')); + } + break; + } + + } + + protected function mountVersioned($path) + { + if (!class_exists('EGroupware\Stylite\Vfs\Versioning\StreamWrapper')) + { + $this->markTestSkipped("No versioning available"); + } + $backup = Vfs::$is_root; + Vfs::$is_root = true; + $url = Versioning\StreamWrapper::PREFIX.$path; + $this->assertTrue(Vfs::mount($url,$path), "Unable to mount $path as versioned"); + Vfs::$is_root = $backup; + } + + /** + * Add some files to the given path so there's something to find. + * + * @param string $path + * + * @return array of paths + */ + protected function addFiles($path) + { + $files = array(); + + // Plain file + $files[] = $file = $path.'test_file.txt'; $this->assertTrue( file_put_contents(Vfs::PREFIX.$file, 'Test for ' . $this->getName() ."\n". Api\DateTime::to()) !== FALSE, 'Unable to write test file - check file permissions for CLI user' ); - $logged_in_files = array_map( - function($path) use ($dir) {return str_replace($dir, '/', $path);}, - Vfs::find($dir) + // Subdirectory + $files[] = $dir = $path.'sub_dir/'; + if(Vfs::is_dir($dir)) + { + Vfs::remove($dir); + } + $this->assertTrue( + Vfs::mkdir($dir), + 'Unable to create subdirectory ' . $dir ); - // Make sure the file's there - $this->assertTrue(in_array('/test_file.txt', $logged_in_files), 'Test file did not get created'); - - // Now we go to the link... - $this->shareLink($dir, Sharing::WRITABLE, array('share_writable' => TRUE)); - $files = Vfs::find(Vfs::get_home_dir()); - - // Make sure files are the same - $this->assertEquals($logged_in_files, $files); - - // Make sure all are writable - foreach($files as $file) - { - // Root is not writable - if($file == '/') continue; - - $this->assertTrue(Vfs::is_writable($file), $file . ' was not writable'); - } + // File in a subdirectory + $files[] = $file = $dir.'subdir_test_file.txt'; + $this->assertTrue( + file_put_contents(Vfs::PREFIX.$file, 'Test for ' . $this->getName() ."\n". Api\DateTime::to()) !== FALSE, + 'Unable to write test file - check file permissions for CLI user' + ); + return $files; } /** @@ -177,7 +305,13 @@ class SharingTest extends LoggedInTest // Log out & clear cache LoggedInTest::tearDownAfterClass(); + + // Re-init, since they look at user, fstab, etc. + // Also, further tests that access the filesystem fail if we don't Vfs::clearstatcache(); + Vfs::init_static(); + Vfs\StreamWrapper::init_static(); + // If it's a directory, check to make sure it gives the filemanager UI if(Vfs::is_dir($path))