Commit ea0f0828 authored by webchick's avatar webchick
Browse files

Issue #1598574 by Niklas Fiekas, aspilicious: Convert file.test to PSR-0.

parent 580d3951
<?php
/**
* @file
* Definition of Drupal\system\Tests\File\CopyTest.
*/
namespace Drupal\system\Tests\File;
/**
* Copy related tests.
*/
class CopyTest extends FileHookTestBase {
public static function getInfo() {
return array(
'name' => 'File copying',
'description' => 'Tests the file copy function.',
'group' => 'File API',
);
}
/**
* Test file copying in the normal, base case.
*/
function testNormal() {
$contents = $this->randomName(10);
$source = $this->createFile(NULL, $contents);
$desired_uri = 'public://' . $this->randomName();
// Clone the object so we don't have to worry about the function changing
// our reference copy.
$result = file_copy(clone $source, $desired_uri, FILE_EXISTS_ERROR);
// Check the return status and that the contents changed.
$this->assertTrue($result, t('File copied successfully.'));
$this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were copied correctly.'));
// Check that the correct hooks were called.
$this->assertFileHooksCalled(array('copy', 'insert'));
$this->assertDifferentFile($source, $result);
$this->assertEqual($result->uri, $desired_uri, t('The copied file entity has the desired filepath.'));
$this->assertTrue(file_exists($source->uri), t('The original file still exists.'));
$this->assertTrue(file_exists($result->uri), t('The copied file exists.'));
// Reload the file from the database and check that the changes were
// actually saved.
$this->assertFileUnchanged($result, file_load($result->fid, TRUE));
}
/**
* Test renaming when copying over a file that already exists.
*/
function testExistingRename() {
// Setup a file to overwrite.
$contents = $this->randomName(10);
$source = $this->createFile(NULL, $contents);
$target = $this->createFile();
$this->assertDifferentFile($source, $target);
// Clone the object so we don't have to worry about the function changing
// our reference copy.
$result = file_copy(clone $source, $target->uri, FILE_EXISTS_RENAME);
// Check the return status and that the contents changed.
$this->assertTrue($result, t('File copied successfully.'));
$this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were copied correctly.'));
$this->assertNotEqual($result->uri, $source->uri, t('Returned file path has changed from the original.'));
// Check that the correct hooks were called.
$this->assertFileHooksCalled(array('copy', 'insert'));
// Load all the affected files to check the changes that actually made it
// to the database.
$loaded_source = file_load($source->fid, TRUE);
$loaded_target = file_load($target->fid, TRUE);
$loaded_result = file_load($result->fid, TRUE);
// Verify that the source file wasn't changed.
$this->assertFileUnchanged($source, $loaded_source);
// Verify that what was returned is what's in the database.
$this->assertFileUnchanged($result, $loaded_result);
// Make sure we end up with three distinct files afterwards.
$this->assertDifferentFile($loaded_source, $loaded_target);
$this->assertDifferentFile($loaded_target, $loaded_result);
$this->assertDifferentFile($loaded_source, $loaded_result);
}
/**
* Test replacement when copying over a file that already exists.
*/
function testExistingReplace() {
// Setup a file to overwrite.
$contents = $this->randomName(10);
$source = $this->createFile(NULL, $contents);
$target = $this->createFile();
$this->assertDifferentFile($source, $target);
// Clone the object so we don't have to worry about the function changing
// our reference copy.
$result = file_copy(clone $source, $target->uri, FILE_EXISTS_REPLACE);
// Check the return status and that the contents changed.
$this->assertTrue($result, t('File copied successfully.'));
$this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were overwritten.'));
$this->assertDifferentFile($source, $result);
// Check that the correct hooks were called.
$this->assertFileHooksCalled(array('load', 'copy', 'update'));
// Load all the affected files to check the changes that actually made it
// to the database.
$loaded_source = file_load($source->fid, TRUE);
$loaded_target = file_load($target->fid, TRUE);
$loaded_result = file_load($result->fid, TRUE);
// Verify that the source file wasn't changed.
$this->assertFileUnchanged($source, $loaded_source);
// Verify that what was returned is what's in the database.
$this->assertFileUnchanged($result, $loaded_result);
// Target file was reused for the result.
$this->assertFileUnchanged($loaded_target, $loaded_result);
}
/**
* Test that copying over an existing file fails when FILE_EXISTS_ERROR is
* specified.
*/
function testExistingError() {
$contents = $this->randomName(10);
$source = $this->createFile();
$target = $this->createFile(NULL, $contents);
$this->assertDifferentFile($source, $target);
// Clone the object so we don't have to worry about the function changing
// our reference copy.
$result = file_copy(clone $source, $target->uri, FILE_EXISTS_ERROR);
// Check the return status and that the contents were not changed.
$this->assertFalse($result, t('File copy failed.'));
$this->assertEqual($contents, file_get_contents($target->uri), t('Contents of file were not altered.'));
// Check that the correct hooks were called.
$this->assertFileHooksCalled(array());
$this->assertFileUnchanged($source, file_load($source->fid, TRUE));
$this->assertFileUnchanged($target, file_load($target->fid, TRUE));
}
}
<?php
/**
* @file
* Definition of Drupal\system\Tests\File\DeleteTest.
*/
namespace Drupal\system\Tests\File;
/**
* Deletion related tests.
*/
class DeleteTest extends FileHookTestBase {
public static function getInfo() {
return array(
'name' => 'File delete',
'description' => 'Tests the file delete function.',
'group' => 'File API',
);
}
/**
* Tries deleting a normal file (as opposed to a directory, symlink, etc).
*/
function testUnused() {
$file = $this->createFile();
// Check that deletion removes the file and database record.
$this->assertTrue(is_file($file->uri), t('File exists.'));
$file->delete();
$this->assertFileHooksCalled(array('delete', 'load'));
$this->assertFalse(file_exists($file->uri), t('Test file has actually been deleted.'));
$this->assertFalse(file_load($file->fid), t('File was removed from the database.'));
}
/**
* Tries deleting a file that is in use.
*/
function testInUse() {
$file = $this->createFile();
file_usage_add($file, 'testing', 'test', 1);
file_usage_add($file, 'testing', 'test', 1);
file_usage_delete($file, 'testing', 'test', 1);
$usage = file_usage_list($file);
$this->assertEqual($usage['testing']['test'], array(1 => 1), t('Test file is still in use.'));
$this->assertTrue(file_exists($file->uri), t('File still exists on the disk.'));
$this->assertTrue(file_load($file->fid), t('File still exists in the database.'));
// Clear out the call to hook_file_load().
file_test_reset();
file_usage_delete($file, 'testing', 'test', 1);
$usage = file_usage_list($file);
$this->assertFileHooksCalled(array('load', 'update'));
$this->assertTrue(empty($usage), t('File usage data was removed.'));
$this->assertTrue(file_exists($file->uri), 'File still exists on the disk.');
$file = file_load($file->fid);
$this->assertTrue($file, 'File still exists in the database.');
$this->assertEqual($file->status, 0, 'File is temporary.');
file_test_reset();
// Call system_cron() to clean up the file. Make sure the timestamp
// of the file is older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
db_update('file_managed')
->fields(array(
'timestamp' => REQUEST_TIME - (DRUPAL_MAXIMUM_TEMP_FILE_AGE + 1),
))
->condition('fid', $file->fid)
->execute();
drupal_cron_run();
// system_cron() loads
$this->assertFileHooksCalled(array('load', 'delete'));
$this->assertFalse(file_exists($file->uri), t('File has been deleted after its last usage was removed.'));
$this->assertFalse(file_load($file->fid), t('File was removed from the database.'));
}
}
<?php
/**
* @file
* Definition of Drupal\system\Tests\File\DirectoryTest.
*/
namespace Drupal\system\Tests\File;
/**
* Directory related tests.
*/
class DirectoryTest extends FileTestBase {
public static function getInfo() {
return array(
'name' => 'File paths and directories',
'description' => 'Tests operations dealing with directories.',
'group' => 'File API',
);
}
/**
* Test directory handling functions.
*/
function testFileCheckDirectoryHandling() {
// A directory to operate on.
$directory = file_default_scheme() . '://' . $this->randomName() . '/' . $this->randomName();
$this->assertFalse(is_dir($directory), t('Directory does not exist prior to testing.'));
// Non-existent directory.
$this->assertFalse(file_prepare_directory($directory, 0), t('Error reported for non-existing directory.'), 'File');
// Make a directory.
$this->assertTrue(file_prepare_directory($directory, FILE_CREATE_DIRECTORY), t('No error reported when creating a new directory.'), 'File');
// Make sure directory actually exists.
$this->assertTrue(is_dir($directory), t('Directory actually exists.'), 'File');
if (substr(PHP_OS, 0, 3) != 'WIN') {
// PHP on Windows doesn't support any kind of useful read-only mode for
// directories. When executing a chmod() on a directory, PHP only sets the
// read-only flag, which doesn't prevent files to actually be written
// in the directory on any recent version of Windows.
// Make directory read only.
@drupal_chmod($directory, 0444);
$this->assertFalse(file_prepare_directory($directory, 0), t('Error reported for a non-writeable directory.'), 'File');
// Test directory permission modification.
$this->assertTrue(file_prepare_directory($directory, FILE_MODIFY_PERMISSIONS), t('No error reported when making directory writeable.'), 'File');
}
// Test that the directory has the correct permissions.
$this->assertDirectoryPermissions($directory, variable_get('file_chmod_directory', 0775));
// Remove .htaccess file to then test that it gets re-created.
@drupal_unlink(file_default_scheme() . '://.htaccess');
$this->assertFalse(is_file(file_default_scheme() . '://.htaccess'), t('Successfully removed the .htaccess file in the files directory.'), 'File');
file_ensure_htaccess();
$this->assertTrue(is_file(file_default_scheme() . '://.htaccess'), t('Successfully re-created the .htaccess file in the files directory.'), 'File');
// Verify contents of .htaccess file.
$file = file_get_contents(file_default_scheme() . '://.htaccess');
$this->assertEqual($file, "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nOptions None\nOptions +FollowSymLinks", t('The .htaccess file contains the proper content.'), 'File');
}
/**
* This will take a directory and path, and find a valid filepath that is not
* taken by another file.
*/
function testFileCreateNewFilepath() {
// First we test against an imaginary file that does not exist in a
// directory.
$basename = 'xyz.txt';
$directory = 'core/misc';
$original = $directory . '/' . $basename;
$path = file_create_filename($basename, $directory);
$this->assertEqual($path, $original, t('New filepath %new equals %original.', array('%new' => $path, '%original' => $original)), 'File');
// Then we test against a file that already exists within that directory.
$basename = 'druplicon.png';
$original = $directory . '/' . $basename;
$expected = $directory . '/druplicon_0.png';
$path = file_create_filename($basename, $directory);
$this->assertEqual($path, $expected, t('Creating a new filepath from %original equals %new (expected %expected).', array('%new' => $path, '%original' => $original, '%expected' => $expected)), 'File');
// @TODO: Finally we copy a file into a directory several times, to ensure a properly iterating filename suffix.
}
/**
* This will test the filepath for a destination based on passed flags and
* whether or not the file exists.
*
* If a file exists, file_destination($destination, $replace) will either
* return:
* - the existing filepath, if $replace is FILE_EXISTS_REPLACE
* - a new filepath if FILE_EXISTS_RENAME
* - an error (returning FALSE) if FILE_EXISTS_ERROR.
* If the file doesn't currently exist, then it will simply return the
* filepath.
*/
function testFileDestination() {
// First test for non-existent file.
$destination = 'core/misc/xyz.txt';
$path = file_destination($destination, FILE_EXISTS_REPLACE);
$this->assertEqual($path, $destination, t('Non-existing filepath destination is correct with FILE_EXISTS_REPLACE.'), 'File');
$path = file_destination($destination, FILE_EXISTS_RENAME);
$this->assertEqual($path, $destination, t('Non-existing filepath destination is correct with FILE_EXISTS_RENAME.'), 'File');
$path = file_destination($destination, FILE_EXISTS_ERROR);
$this->assertEqual($path, $destination, t('Non-existing filepath destination is correct with FILE_EXISTS_ERROR.'), 'File');
$destination = 'core/misc/druplicon.png';
$path = file_destination($destination, FILE_EXISTS_REPLACE);
$this->assertEqual($path, $destination, t('Existing filepath destination remains the same with FILE_EXISTS_REPLACE.'), 'File');
$path = file_destination($destination, FILE_EXISTS_RENAME);
$this->assertNotEqual($path, $destination, t('A new filepath destination is created when filepath destination already exists with FILE_EXISTS_RENAME.'), 'File');
$path = file_destination($destination, FILE_EXISTS_ERROR);
$this->assertEqual($path, FALSE, t('An error is returned when filepath destination already exists with FILE_EXISTS_ERROR.'), 'File');
}
/**
* Ensure that the file_directory_temp() function always returns a value.
*/
function testFileDirectoryTemp() {
// Start with an empty variable to ensure we have a clean slate.
variable_set('file_temporary_path', '');
$tmp_directory = file_directory_temp();
$this->assertEqual(empty($tmp_directory), FALSE, t('file_directory_temp() returned a non-empty value.'));
$setting = variable_get('file_temporary_path', '');
$this->assertEqual($setting, $tmp_directory, t("The 'file_temporary_path' variable has the same value that file_directory_temp() returned."));
}
}
<?php
/**
* @file
* Definition of Drupal\system\Tests\File\DownloadTest.
*/
namespace Drupal\system\Tests\File;
/**
* Tests for download/file transfer functions.
*/
class DownloadTest extends FileTestBase {
public static function getInfo() {
return array(
'name' => 'File download',
'description' => 'Tests for file download/transfer functions.',
'group' => 'File API',
);
}
function setUp() {
parent::setUp('file_test');
// Clear out any hook calls.
file_test_reset();
}
/**
* Test the public file transfer system.
*/
function testPublicFileTransfer() {
// Test generating an URL to a created file.
$file = $this->createFile();
$url = file_create_url($file->uri);
// URLs can't contain characters outside the ASCII set so $filename has to be
// encoded.
$filename = $GLOBALS['base_url'] . '/' . file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath() . '/' . rawurlencode($file->filename);
$this->assertEqual($filename, $url, t('Correctly generated a URL for a created file.'));
$this->drupalHead($url);
$this->assertResponse(200, t('Confirmed that the generated URL is correct by downloading the created file.'));
// Test generating an URL to a shipped file (i.e. a file that is part of
// Drupal core, a module or a theme, for example a JavaScript file).
$filepath = 'core/misc/jquery.js';
$url = file_create_url($filepath);
$this->assertEqual($GLOBALS['base_url'] . '/' . $filepath, $url, t('Correctly generated a URL for a shipped file.'));
$this->drupalHead($url);
$this->assertResponse(200, t('Confirmed that the generated URL is correct by downloading the shipped file.'));
}
/**
* Test the private file transfer system.
*/
function testPrivateFileTransfer() {
// Set file downloads to private so handler functions get called.
// Create a file.
$contents = $this->randomName(8);
$file = $this->createFile(NULL, $contents, 'private');
$url = file_create_url($file->uri);
// Set file_test access header to allow the download.
file_test_set_return('download', array('x-foo' => 'Bar'));
$this->drupalGet($url);
$headers = $this->drupalGetHeaders();
$this->assertEqual($headers['x-foo'], 'Bar', t('Found header set by file_test module on private download.'));
$this->assertResponse(200, t('Correctly allowed access to a file when file_test provides headers.'));
// Test that the file transfered correctly.
$this->assertEqual($contents, $this->content, t('Contents of the file are correct.'));
// Deny access to all downloads via a -1 header.
file_test_set_return('download', -1);
$this->drupalHead($url);
$this->assertResponse(403, t('Correctly denied access to a file when file_test sets the header to -1.'));
// Try non-existent file.
$url = file_create_url('private://' . $this->randomName());
$this->drupalHead($url);
$this->assertResponse(404, t('Correctly returned 404 response for a non-existent file.'));
}
/**
* Test file_create_url().
*/
function testFileCreateUrl() {
global $base_url, $script_path;
// Tilde (~) is excluded from this test because it is encoded by
// rawurlencode() in PHP 5.2 but not in PHP 5.3, as per RFC 3986.
// @see http://www.php.net/manual/function.rawurlencode.php#86506
$basename = " -._!$'\"()*@[]?&+%#,;=:\n\x00" . // "Special" ASCII characters.
"%23%25%26%2B%2F%3F" . // Characters that look like a percent-escaped string.
"éøïвβ中國書۞"; // Characters from various non-ASCII alphabets.
$basename_encoded = '%20-._%21%24%27%22%28%29%2A%40%5B%5D%3F%26%2B%25%23%2C%3B%3D%3A__' .
'%2523%2525%2526%252B%252F%253F' .
'%C3%A9%C3%B8%C3%AF%D0%B2%CE%B2%E4%B8%AD%E5%9C%8B%E6%9B%B8%DB%9E';
// Public files should not be served by Drupal, so their URLs should not be
// generated by url(), whereas private files should be served by Drupal, so
// their URLs should be generated by url(). The difference is most apparent
// when $script_path is not empty (i.e., when not using clean URLs).
$script_path_original = $script_path;
foreach (array('', 'index.php/') as $script_path) {
$this->checkUrl('public', '', $basename, $base_url . '/' . file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath() . '/' . $basename_encoded);
$this->checkUrl('private', '', $basename, $base_url . '/' . $script_path . 'system/files/' . $basename_encoded);
}
$script_path = $script_path_original;
}
/**
* Download a file from the URL generated by file_create_url().
*
* Create a file with the specified scheme, directory and filename; check that
* the URL generated by file_create_url() for the specified file equals the
* specified URL; fetch the URL and then compare the contents to the file.
*
* @param $scheme
* A scheme, e.g. "public"
* @param $directory
* A directory, possibly ""
* @param $filename
* A filename
* @param $expected_url
* The expected URL
*/
private function checkUrl($scheme, $directory, $filename, $expected_url) {
// Convert $filename to a valid filename, i.e. strip characters not
// supported by the filesystem, and create the file in the specified
// directory.
$filepath = file_create_filename($filename, $directory);
$directory_uri = $scheme . '://' . dirname($filepath);
file_prepare_directory($directory_uri, FILE_CREATE_DIRECTORY);
$file = $this->createFile($filepath, NULL, $scheme);
$url = file_create_url($file->uri);
$this->assertEqual($url, $expected_url, t('Generated URL matches expected URL.'));
if ($scheme == 'private') {
// Tell the implementation of hook_file_download() in file_test.module
// that this file may be downloaded.
file_test_set_return('download', array('x-foo' => 'Bar'));
}
$this->drupalGet($url);
if ($this->assertResponse(200) == 'pass') {
$this->assertRaw(file_get_contents($file->uri), t('Contents of the file are correct.'));
}
$file->delete();
}
}
<?php
/**
* @file
* Definition of Drupal\system\Tests\File\FileHookTestBase.
*/
namespace Drupal\system\Tests\File;
/**
* Base class for file tests that use the file_test module to test uploads and
* hooks.
*/
class FileHookTestBase extends FileTestBase {
function setUp() {
// Install file_test module
parent::setUp('file_test');
// Clear out any hook calls.
file_test_reset();
}
/**
* Assert that all of the specified hook_file_* hooks were called once, other
* values result in failure.
*
* @param $expected
* Array with string containing with the hook name, e.g. 'load', 'save',
* 'insert', etc.
*/
function assertFileHooksCalled($expected) {
// Determine which hooks were called.
$actual = array_keys(array_filter(file_test_get_all_calls()));
// Determine if there were any expected that were not called.
$uncalled = array_diff($expected, $actual);
if (count($uncalled)) {
$this->assertTrue(FALSE, t('Expected hooks %expected to be called but %uncalled was not called.', array('%expected' => implode(', ', $expected), '%uncalled' => implode(', ', $uncalled))));
}
else {
$this->assertTrue(TRUE, t('All the expected hooks were called: %expected', array('%expected' => empty($expected) ? t('(none)') : implode(', ', $expected))));
}
// Determine if there were any unexpected calls.
$unexpected = array_diff($actual, $expected);
if (count($unexpected)) {
$this->assertTrue(FALSE, t('Unexpected hooks were called: %unexpected.', array('%unexpected' => empty($unexpected) ? t('(none)') : implode(', ', $unexpected))));
}
else {
$this->assertTrue(TRUE, t('No unexpected hooks were called.'));
}
}
/**
* Assert that a hook_file_* hook was called a certain number of times.
*
* @param $hook
* String with the hook name, e.g. 'load', 'save', 'insert', etc.
* @param $expected_count
* Optional integer count.