 core/includes/file.inc                             |  623 -----
 core/modules/file/file.api.php                     |  158 ++
 core/modules/file/file.install                     |  137 +
 core/modules/file/file.module                      |  683 ++++-
 .../File => modules/file/lib/Drupal/file}/File.php |    4 +-
 .../lib/Drupal/file}/FileStorageController.php     |    4 +-
 .../file/lib/Drupal/file/Tests/CopyTest.php        |  153 ++
 .../file/lib/Drupal/file/Tests/DeleteTest.php      |   78 +
 .../file/lib/Drupal/file/Tests/DownloadTest.php    |  152 ++
 .../lib/Drupal/file/Tests/FileManagedTestBase.php  |  114 +
 .../file/lib/Drupal/file/Tests/LoadTest.php        |   91 +
 .../file/lib/Drupal/file/Tests/MoveTest.php        |  168 ++
 .../Drupal/file/Tests/RemoteFileSaveUploadTest.php |   24 +
 .../file/lib/Drupal/file/Tests/SaveDataTest.php    |  142 +
 .../file/lib/Drupal/file/Tests/SaveTest.php        |   77 +
 .../file/lib/Drupal/file/Tests/SaveUploadTest.php  |  328 +++
 .../file/lib/Drupal/file/Tests/SpaceUsedTest.php   |   63 +
 .../file/lib/Drupal/file/Tests/UsageTest.php       |  122 +
 .../file/lib/Drupal/file/Tests/ValidateTest.php    |   47 +
 .../file/lib/Drupal/file/Tests/ValidatorTest.php   |  160 ++
 .../tests}/file_test/file_test.info                |    0
 .../tests}/file_test/file_test.module              |   65 +-
 .../Drupal/file_test/DummyRemoteStreamWrapper.php  |   23 +
 .../lib/Drupal/file_test/DummyStreamWrapper.php    |   39 +
 core/modules/image/image.module                    |    2 +-
 .../lib/Drupal/system/Tests/File/DirectoryTest.php |  131 +
 .../lib/Drupal/system/Tests/File/FileTestBase.php  |  198 ++
 .../lib/Drupal/system/Tests/File/MimeTypeTest.php  |   95 +
 .../Drupal/system/Tests/File/NameMungingTest.php   |   67 +
 .../system/Tests/File/RemoteFileDirectoryTest.php  |   24 +
 .../Tests/File/RemoteFileScanDirectoryTest.php     |   24 +
 .../Tests/File/RemoteFileUnmanagedCopyTest.php     |   24 +
 .../RemoteFileUnmanagedDeleteRecursiveTest.php     |   24 +
 .../Tests/File/RemoteFileUnmanagedDeleteTest.php   |   24 +
 .../Tests/File/RemoteFileUnmanagedMoveTest.php     |   24 +
 .../Tests/File/RemoteFileUnmanagedSaveDataTest.php |   24 +
 .../Drupal/system/Tests/File/ScanDirectoryTest.php |  139 +
 .../Drupal/system/Tests/File/StreamWrapperTest.php |   91 +
 .../Drupal/system/Tests/File/UnmanagedCopyTest.php |   96 +
 .../Tests/File/UnmanagedDeleteRecursiveTest.php    |   84 +
 .../system/Tests/File/UnmanagedDeleteTest.php      |   53 +
 .../Drupal/system/Tests/File/UnmanagedMoveTest.php |   80 +
 .../system/Tests/File/UnmanagedSaveDataTest.php    |   41 +
 .../Drupal/system/Tests/File/UrlRewritingTest.php  |   86 +
 core/modules/system/system.api.php                 |  158 --
 core/modules/system/system.info                    |    1 -
 core/modules/system/system.install                 |  131 -
 core/modules/system/system.module                  |   43 -
 core/modules/system/tests/file.test                | 2807 --------------------
 core/modules/user/user.module                      |    2 +-
 50 files changed, 4117 insertions(+), 3811 deletions(-)

diff --git a/core/includes/file.inc b/core/includes/file.inc
index 133d64f..3248b3a 100644
--- a/core/includes/file.inc
+++ b/core/includes/file.inc
@@ -9,8 +9,6 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Symfony\Component\HttpFoundation\StreamedResponse;
 use Drupal\Core\StreamWrapper\LocalStream;
-use Drupal\Core\File\File;
-
 /**
  * Stream wrapper bit flags that are the basis for composite types.
  *
@@ -578,255 +576,6 @@ function file_save_htaccess($directory, $private = TRUE) {
 }
 
 /**
- * Loads file entities from the database.
- *
- * @param array|bool $fids
- *   An array of file IDs, or FALSE to load all files.
- * @param array $conditions
- *   (deprecated) An associative array of conditions on the {file_managed}
- *   table, where the keys are the database fields and the values are the
- *   values those fields must have. Instead, it is preferable to use
- *   Drupal\entity\EntityFieldQuery to retrieve a list of entity IDs
- *   loadable by this function.
- *
- * @return array
- *   An array of file entities, indexed by fid.
- *
- * @todo Remove $conditions in Drupal 8.
- *
- * @see hook_file_load()
- * @see file_load()
- * @see entity_load()
- * @see Drupal\entity\EntityFieldQuery
- */
-function file_load_multiple($fids = array(), array $conditions = array()) {
-  return entity_load_multiple('file', $fids, $conditions);
-}
-
-/**
- * Loads a single file entity from the database.
- *
- * @param $fid
- *   A file ID.
- *
- * @return Drupal\Core\File\File
- *   A file entity or FALSE if the file was not found.
- *
- * @see hook_file_load()
- * @see file_load_multiple()
- */
-function file_load($fid) {
-  $files = file_load_multiple(array($fid), array());
-  return reset($files);
-}
-
-/**
- * Determines where a file is used.
- *
- * @param Drupal\Core\File\File $file
- *   A file entity.
- *
- * @return
- *   A nested array with usage data. The first level is keyed by module name,
- *   the second by object type and the third by the object id. The value
- *   of the third level contains the usage count.
- *
- * @see file_usage_add()
- * @see file_usage_delete()
- */
-function file_usage_list(File $file) {
-  $result = db_select('file_usage', 'f')
-    ->fields('f', array('module', 'type', 'id', 'count'))
-    ->condition('fid', $file->fid)
-    ->condition('count', 0, '>')
-    ->execute();
-  $references = array();
-  foreach ($result as $usage) {
-    $references[$usage->module][$usage->type][$usage->id] = $usage->count;
-  }
-  return $references;
-}
-
-/**
- * Records that a module is using a file.
- *
- * Examples:
- * - A module that associates files with nodes, so $type would be
- *   'node' and $id would be the node's nid. Files for all revisions are stored
- *   within a single nid.
- * - The User module associates an image with a user, so $type would be 'user'
- *   and the $id would be the user's uid.
- *
- * @param Drupal\Core\File\File $file
- *   A file entity.
- * @param $module
- *   The name of the module using the file.
- * @param $type
- *   The type of the object that contains the referenced file.
- * @param $id
- *   The unique, numeric ID of the object containing the referenced file.
- * @param $count
- *   (optional) The number of references to add to the object. Defaults to 1.
- *
- * @see file_usage_list()
- * @see file_usage_delete()
- */
-function file_usage_add(File $file, $module, $type, $id, $count = 1) {
-  db_merge('file_usage')
-    ->key(array(
-      'fid' => $file->fid,
-      'module' => $module,
-      'type' => $type,
-      'id' => $id,
-    ))
-    ->fields(array('count' => $count))
-    ->expression('count', 'count + :count', array(':count' => $count))
-    ->execute();
-
-  // Make sure that a used file is permament.
-  if ($file->status != FILE_STATUS_PERMANENT) {
-    $file->status = FILE_STATUS_PERMANENT;
-    $file->save();
-  }
-}
-
-/**
- * Removes a record to indicate that a module is no longer using a file.
- *
- * @param Drupal\Core\File\File $file
- *   A file entity.
- * @param $module
- *   The name of the module using the file.
- * @param $type
- *   (optional) The type of the object that contains the referenced file. May
- *   be omitted if all module references to a file are being deleted.
- * @param $id
- *   (optional) The unique, numeric ID of the object containing the referenced
- *   file. May be omitted if all module references to a file are being deleted.
- * @param $count
- *   (optional) The number of references to delete from the object. Defaults to
- *   1. 0 may be specified to delete all references to the file within a
- *   specific object.
- *
- * @see file_usage_add()
- * @see file_usage_list()
- */
-function file_usage_delete(File $file, $module, $type = NULL, $id = NULL, $count = 1) {
-  // Delete rows that have a exact or less value to prevent empty rows.
-  $query = db_delete('file_usage')
-    ->condition('module', $module)
-    ->condition('fid', $file->fid);
-  if ($type && $id) {
-    $query
-      ->condition('type', $type)
-      ->condition('id', $id);
-  }
-  if ($count) {
-    $query->condition('count', $count, '<=');
-  }
-  $result = $query->execute();
-
-  // If the row has more than the specified count decrement it by that number.
-  if (!$result && $count > 0) {
-    $query = db_update('file_usage')
-      ->condition('module', $module)
-      ->condition('fid', $file->fid);
-    if ($type && $id) {
-      $query
-        ->condition('type', $type)
-        ->condition('id', $id);
-    }
-    $query->expression('count', 'count - :count', array(':count' => $count));
-    $query->execute();
-  }
-
-  // If there are no more remaining usages of this file, mark it as temporary,
-  // which result in a delete through system_cron().
-  $usage = file_usage_list($file);
-  if (empty($usage)) {
-    $file->status = 0;
-    $file->save();
-  }
-}
-
-/**
- * Copies a file to a new location and adds a file record to the database.
- *
- * This function should be used when manipulating files that have records
- * stored in the database. This is a powerful function that in many ways
- * performs like an advanced version of copy().
- * - Checks if $source and $destination are valid and readable/writable.
- * - Checks that $source is not equal to $destination; if they are an error
- *   is reported.
- * - If file already exists in $destination either the call will error out,
- *   replace the file or rename the file based on the $replace parameter.
- * - Adds the new file to the files database. If the source file is a
- *   temporary file, the resulting file will also be a temporary file. See
- *   file_save_upload() for details on temporary files.
- *
- * @param Drupal\Core\File\File $source
- *   A file entity.
- * @param $destination
- *   A string containing the destination that $source should be copied to.
- *   This must be a stream wrapper URI.
- * @param $replace
- *   Replace behavior when the destination file already exists:
- *   - FILE_EXISTS_REPLACE - Replace the existing file. If a managed file with
- *       the destination name exists then its database entry will be updated. If
- *       no database entry is found then a new one will be created.
- *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
- *       unique.
- *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
- *
- * @return
- *   File object if the copy is successful, or FALSE in the event of an error.
- *
- * @see file_unmanaged_copy()
- * @see hook_file_copy()
- */
-function file_copy(File $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
-  if (!file_valid_uri($destination)) {
-    if (($realpath = drupal_realpath($source->uri)) !== FALSE) {
-      watchdog('file', 'File %file (%realpath) could not be copied because the destination %destination is invalid. This is often caused by improper use of file_copy() or a missing stream wrapper.', array('%file' => $source->uri, '%realpath' => $realpath, '%destination' => $destination));
-    }
-    else {
-      watchdog('file', 'File %file could not be copied because the destination %destination is invalid. This is often caused by improper use of file_copy() or a missing stream wrapper.', array('%file' => $source->uri, '%destination' => $destination));
-    }
-    drupal_set_message(t('The specified file %file could not be copied because the destination is invalid. More information is available in the system log.', array('%file' => $source->uri)), 'error');
-    return FALSE;
-  }
-
-  if ($uri = file_unmanaged_copy($source->uri, $destination, $replace)) {
-    $file = clone $source;
-    $file->fid = NULL;
-    $file->uri = $uri;
-    $file->filename = drupal_basename($uri);
-    // If we are replacing an existing file re-use its database record.
-    if ($replace == FILE_EXISTS_REPLACE) {
-      $existing_files = file_load_multiple(array(), array('uri' => $uri));
-      if (count($existing_files)) {
-        $existing = reset($existing_files);
-        $file->fid = $existing->fid;
-        $file->filename = $existing->filename;
-      }
-    }
-    // If we are renaming around an existing file (rather than a directory),
-    // use its basename for the filename.
-    elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
-      $file->filename = drupal_basename($destination);
-    }
-
-    $file->save();
-
-    // Inform modules that the file has been copied.
-    module_invoke_all('file_copy', $file, $source);
-
-    return $file;
-  }
-  return FALSE;
-}
-
-/**
  * Determines whether the URI has a valid scheme for file API operations.
  *
  * There must be a scheme and it must be a Drupal-provided scheme like
@@ -1001,86 +750,6 @@ function file_destination($destination, $replace) {
 }
 
 /**
- * Moves a file to a new location and update the file's database entry.
- *
- * Moving a file is performed by copying the file to the new location and then
- * deleting the original.
- * - Checks if $source and $destination are valid and readable/writable.
- * - Performs a file move if $source is not equal to $destination.
- * - If file already exists in $destination either the call will error out,
- *   replace the file or rename the file based on the $replace parameter.
- * - Adds the new file to the files database.
- *
- * @param Drupal\Core\File\File $source
- *   A file entity.
- * @param $destination
- *   A string containing the destination that $source should be moved to.
- *   This must be a stream wrapper URI.
- * @param $replace
- *   Replace behavior when the destination file already exists:
- *   - FILE_EXISTS_REPLACE - Replace the existing file. If a managed file with
- *       the destination name exists then its database entry will be updated and
- *       $source->delete() called after invoking hook_file_move().
- *       If no database entry is found then the source files record will be
- *       updated.
- *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
- *       unique.
- *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
- *
- * @return Drupal\Core\File\File
- *   Resulting file entity for success, or FALSE in the event of an error.
- *
- * @see file_unmanaged_move()
- * @see hook_file_move()
- */
-function file_move(File $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
-  if (!file_valid_uri($destination)) {
-    if (($realpath = drupal_realpath($source->uri)) !== FALSE) {
-      watchdog('file', 'File %file (%realpath) could not be moved because the destination %destination is invalid. This may be caused by improper use of file_move() or a missing stream wrapper.', array('%file' => $source->uri, '%realpath' => $realpath, '%destination' => $destination));
-    }
-    else {
-      watchdog('file', 'File %file could not be moved because the destination %destination is invalid. This may be caused by improper use of file_move() or a missing stream wrapper.', array('%file' => $source->uri, '%destination' => $destination));
-    }
-    drupal_set_message(t('The specified file %file could not be moved because the destination is invalid. More information is available in the system log.', array('%file' => $source->uri)), 'error');
-    return FALSE;
-  }
-
-  if ($uri = file_unmanaged_move($source->uri, $destination, $replace)) {
-    $delete_source = FALSE;
-
-    $file = clone $source;
-    $file->uri = $uri;
-    // If we are replacing an existing file re-use its database record.
-    if ($replace == FILE_EXISTS_REPLACE) {
-      $existing_files = file_load_multiple(array(), array('uri' => $uri));
-      if (count($existing_files)) {
-        $existing = reset($existing_files);
-        $delete_source = TRUE;
-        $file->fid = $existing->fid;
-      }
-    }
-    // If we are renaming around an existing file (rather than a directory),
-    // use its basename for the filename.
-    elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
-      $file->filename = drupal_basename($destination);
-    }
-
-    $file->save();
-
-    // Inform modules that the file has been moved.
-    module_invoke_all('file_move', $file, $source);
-
-    // Delete the original if it's not in use elsewhere.
-    if ($delete_source && !file_usage_list($source)) {
-      $source->delete();
-    }
-
-    return $file;
-  }
-  return FALSE;
-}
-
-/**
  * Moves a file to a new location without database changes or hook invocation.
  *
  * @param $source
@@ -1617,267 +1286,6 @@ function drupal_move_uploaded_file($filename, $uri) {
 }
 
 /**
- * Checks that a file meets the criteria specified by the validators.
- *
- * After executing the validator callbacks specified hook_file_validate() will
- * also be called to allow other modules to report errors about the file.
- *
- * @param Drupal\Core\File\File $file
- *   A file entity.
- * @param $validators
- *   An optional, associative array of callback functions used to validate the
- *   file. The keys are function names and the values arrays of callback
- *   parameters which will be passed in after the file entity. The
- *   functions should return an array of error messages; an empty array
- *   indicates that the file passed validation. The functions will be called in
- *   the order specified.
- *
- * @return
- *   An array containing validation error messages.
- *
- * @see hook_file_validate()
- */
-function file_validate(File $file, $validators = array()) {
-  // Call the validation functions specified by this function's caller.
-  $errors = array();
-  foreach ($validators as $function => $args) {
-    if (function_exists($function)) {
-      array_unshift($args, $file);
-      $errors = array_merge($errors, call_user_func_array($function, $args));
-    }
-  }
-
-  // Let other modules perform validation on the new file.
-  return array_merge($errors, module_invoke_all('file_validate', $file));
-}
-
-/**
- * Checks for files with names longer than can be stored in the database.
- *
- * @param Drupal\Core\File\File $file
- *   A file entity.
- *
- * @return
- *   An array. If the file name is too long, it will contain an error message.
- */
-function file_validate_name_length(File $file) {
-  $errors = array();
-
-  if (empty($file->filename)) {
-    $errors[] = t("The file's name is empty. Please give a name to the file.");
-  }
-  if (strlen($file->filename) > 240) {
-    $errors[] = t("The file's name exceeds the 240 characters limit. Please rename the file and try again.");
-  }
-  return $errors;
-}
-
-/**
- * Checks that the filename ends with an allowed extension.
- *
- * @param Drupal\Core\File\File $file
- *   A file entity.
- * @param $extensions
- *   A string with a space separated list of allowed extensions.
- *
- * @return
- *   An array. If the file extension is not allowed, it will contain an error
- *   message.
- *
- * @see hook_file_validate()
- */
-function file_validate_extensions(File $file, $extensions) {
-  $errors = array();
-
-  $regex = '/\.(' . preg_replace('/ +/', '|', preg_quote($extensions)) . ')$/i';
-  if (!preg_match($regex, $file->filename)) {
-    $errors[] = t('Only files with the following extensions are allowed: %files-allowed.', array('%files-allowed' => $extensions));
-  }
-  return $errors;
-}
-
-/**
- * Checks that the file's size is below certain limits.
- *
- * This check is not enforced for the user #1.
- *
- * @param Drupal\Core\File\File $file
- *   A file entity.
- * @param $file_limit
- *   An integer specifying the maximum file size in bytes. Zero indicates that
- *   no limit should be enforced.
- * @param $user_limit
- *   An integer specifying the maximum number of bytes the user is allowed.
- *   Zero indicates that no limit should be enforced.
- *
- * @return
- *   An array. If the file size exceeds limits, it will contain an error
- *   message.
- *
- * @see hook_file_validate()
- */
-function file_validate_size(File $file, $file_limit = 0, $user_limit = 0) {
-  global $user;
-
-  $errors = array();
-
-  // Bypass validation for uid  = 1.
-  if ($user->uid != 1) {
-    if ($file_limit && $file->filesize > $file_limit) {
-      $errors[] = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size($file->filesize), '%maxsize' => format_size($file_limit)));
-    }
-
-    // Save a query by only calling file_space_used() when a limit is provided.
-    if ($user_limit && (file_space_used($user->uid) + $file->filesize) > $user_limit) {
-      $errors[] = t('The file is %filesize which would exceed your disk quota of %quota.', array('%filesize' => format_size($file->filesize), '%quota' => format_size($user_limit)));
-    }
-  }
-  return $errors;
-}
-
-/**
- * Checks that the file is recognized by image_get_info() as an image.
- *
- * @param Drupal\Core\File\File $file
- *   A file entity.
- *
- * @return
- *   An array. If the file is not an image, it will contain an error message.
- *
- * @see hook_file_validate()
- */
-function file_validate_is_image(File $file) {
-  $errors = array();
-
-  $info = image_get_info($file->uri);
-  if (!$info || empty($info['extension'])) {
-    $errors[] = t('Only JPEG, PNG and GIF images are allowed.');
-  }
-
-  return $errors;
-}
-
-/**
- * Verifies that image dimensions are within the specified maximum and minimum.
- *
- * Non-image files will be ignored. If a image toolkit is available the image
- * will be scaled to fit within the desired maximum dimensions.
- *
- * @param Drupal\Core\File\File $file
- *   A file entity. This function may resize the file affecting its size.
- * @param $maximum_dimensions
- *   An optional string in the form WIDTHxHEIGHT e.g. '640x480' or '85x85'. If
- *   an image toolkit is installed the image will be resized down to these
- *   dimensions. A value of 0 indicates no restriction on size, so resizing
- *   will be attempted.
- * @param $minimum_dimensions
- *   An optional string in the form WIDTHxHEIGHT. This will check that the
- *   image meets a minimum size. A value of 0 indicates no restriction.
- *
- * @return
- *   An array. If the file is an image and did not meet the requirements, it
- *   will contain an error message.
- *
- * @see hook_file_validate()
- */
-function file_validate_image_resolution(File $file, $maximum_dimensions = 0, $minimum_dimensions = 0) {
-  $errors = array();
-
-  // Check first that the file is an image.
-  if ($info = image_get_info($file->uri)) {
-    if ($maximum_dimensions) {
-      // Check that it is smaller than the given dimensions.
-      list($width, $height) = explode('x', $maximum_dimensions);
-      if ($info['width'] > $width || $info['height'] > $height) {
-        // Try to resize the image to fit the dimensions.
-        if ($image = image_load($file->uri)) {
-          image_scale($image, $width, $height);
-          image_save($image);
-          $file->filesize = $image->info['file_size'];
-          drupal_set_message(t('The image was resized to fit within the maximum allowed dimensions of %dimensions pixels.', array('%dimensions' => $maximum_dimensions)));
-        }
-        else {
-          $errors[] = t('The image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => $maximum_dimensions));
-        }
-      }
-    }
-
-    if ($minimum_dimensions) {
-      // Check that it is larger than the given dimensions.
-      list($width, $height) = explode('x', $minimum_dimensions);
-      if ($info['width'] < $width || $info['height'] < $height) {
-        $errors[] = t('The image is too small; the minimum dimensions are %dimensions pixels.', array('%dimensions' => $minimum_dimensions));
-      }
-    }
-  }
-
-  return $errors;
-}
-
-/**
- * Saves a file to the specified destination and creates a database entry.
- *
- * @param $data
- *   A string containing the contents of the file.
- * @param $destination
- *   A string containing the destination URI. This must be a stream wrapper URI.
- *   If no value is provided, a randomized name will be generated and the file
- *   will be saved using Drupal's default files scheme, usually "public://".
- * @param $replace
- *   Replace behavior when the destination file already exists:
- *   - FILE_EXISTS_REPLACE - Replace the existing file. If a managed file with
- *       the destination name exists then its database entry will be updated. If
- *       no database entry is found then a new one will be created.
- *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
- *       unique.
- *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
- *
- * @return Drupal\Core\File\File
- *   A file entity, or FALSE on error.
- *
- * @see file_unmanaged_save_data()
- */
-function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
-  global $user;
-
-  if (empty($destination)) {
-    $destination = file_default_scheme() . '://';
-  }
-  if (!file_valid_uri($destination)) {
-    watchdog('file', 'The data could not be saved because the destination %destination is invalid. This may be caused by improper use of file_save_data() or a missing stream wrapper.', array('%destination' => $destination));
-    drupal_set_message(t('The data could not be saved because the destination is invalid. More information is available in the system log.'), 'error');
-    return FALSE;
-  }
-
-  if ($uri = file_unmanaged_save_data($data, $destination, $replace)) {
-    // Create a file entity.
-    $file = entity_create('file', array(
-      'uri' => $uri,
-      'uid' => $user->uid,
-      'status' => FILE_STATUS_PERMANENT,
-    ));
-    // If we are replacing an existing file re-use its database record.
-    if ($replace == FILE_EXISTS_REPLACE) {
-      $existing_files = file_load_multiple(array(), array('uri' => $uri));
-      if (count($existing_files)) {
-        $existing = reset($existing_files);
-        $file->fid = $existing->fid;
-        $file->filename = $existing->filename;
-      }
-    }
-    // If we are renaming around an existing file (rather than a directory),
-    // use its basename for the filename.
-    elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
-      $file->filename = drupal_basename($destination);
-    }
-
-    $file->save();
-    return $file;
-  }
-  return FALSE;
-}
-
-/**
  * Saves a file to the specified destination without invoking file API.
  *
  * This function is identical to file_save_data() except the file will not be
@@ -2451,36 +1859,5 @@ function file_directory_temp() {
 }
 
 /**
- * Examines a file entity and returns appropriate content headers for download.
- *
- * @param Drupal\Core\File\File $file
- *   A file entity.
- *
- * @return
- *   An associative array of headers, as expected by
- *   \Symfony\Component\HttpFoundation\StreamedResponse.
- */
-function file_get_content_headers(File $file) {
-  $name = mime_header_encode($file->filename);
-  $type = mime_header_encode($file->filemime);
-  // Serve images, text, and flash content for display rather than download.
-  $inline_types = variable_get('file_inline_types', array('^text/', '^image/', 'flash$'));
-  $disposition = 'attachment';
-  foreach ($inline_types as $inline_type) {
-    // Exclamation marks are used as delimiters to avoid escaping slashes.
-    if (preg_match('!' . $inline_type . '!', $file->filemime)) {
-      $disposition = 'inline';
-    }
-  }
-
-  return array(
-    'Content-Type' => $type . '; name="' . $name . '"',
-    'Content-Length' => $file->filesize,
-    'Content-Disposition' => $disposition . '; filename="' . $name . '"',
-    'Cache-Control' => 'private',
-  );
-}
-
-/**
  * @} End of "defgroup file".
  */
diff --git a/core/modules/file/file.api.php b/core/modules/file/file.api.php
index 7f20d83..b4c2d2b 100644
--- a/core/modules/file/file.api.php
+++ b/core/modules/file/file.api.php
@@ -5,6 +5,164 @@
  * Hooks for file module.
  */
 
+
+/**
+ * Load additional information into file entities.
+ *
+ * file_load_multiple() calls this hook to allow modules to load
+ * additional information into each file.
+ *
+ * @param $files
+ *   An array of file entities, indexed by fid.
+ *
+ * @see file_load_multiple()
+ * @see file_load()
+ */
+function hook_file_load($files) {
+  // Add the upload specific data into the file entity.
+  $result = db_query('SELECT * FROM {upload} u WHERE u.fid IN (:fids)', array(':fids' => array_keys($files)))->fetchAll(PDO::FETCH_ASSOC);
+  foreach ($result as $record) {
+    foreach ($record as $key => $value) {
+      $files[$record['fid']]->$key = $value;
+    }
+  }
+}
+
+/**
+ * Check that files meet a given criteria.
+ *
+ * This hook lets modules perform additional validation on files. They're able
+ * to report a failure by returning one or more error messages.
+ *
+ * @param Drupal\file\File $file
+ *   The file entity being validated.
+ * @return
+ *   An array of error messages. If there are no problems with the file return
+ *   an empty array.
+ *
+ * @see file_validate()
+ */
+function hook_file_validate(Drupal\file\File $file) {
+  $errors = array();
+
+  if (empty($file->filename)) {
+    $errors[] = t("The file's name is empty. Please give a name to the file.");
+  }
+  if (strlen($file->filename) > 255) {
+    $errors[] = t("The file's name exceeds the 255 characters limit. Please rename the file and try again.");
+  }
+
+  return $errors;
+}
+
+/**
+ * Act on a file being inserted or updated.
+ *
+ * This hook is called when a file has been added to the database. The hook
+ * doesn't distinguish between files created as a result of a copy or those
+ * created by an upload.
+ *
+ * @param Drupal\file\File $file
+ *   The file entity that is about to be created or updated.
+ */
+function hook_file_presave(Drupal\file\File $file) {
+  // Change the file timestamp to an hour prior.
+  $file->timestamp -= 3600;
+}
+
+/**
+ * Respond to a file being added.
+ *
+ * This hook is called after a file has been added to the database. The hook
+ * doesn't distinguish between files created as a result of a copy or those
+ * created by an upload.
+ *
+ * @param Drupal\file\File $file
+ *   The file that has been added.
+ */
+function hook_file_insert(Drupal\file\File $file) {
+  // Add a message to the log, if the file is a jpg
+  $validate = file_validate_extensions($file, 'jpg');
+  if (empty($validate)) {
+    watchdog('file', 'A jpg has been added.');
+  }
+}
+
+/**
+ * Respond to a file being updated.
+ *
+ * This hook is called when an existing file is saved.
+ *
+ * @param Drupal\file\File $file
+ *   The file that has just been updated.
+ */
+function hook_file_update(Drupal\file\File $file) {
+
+}
+
+/**
+ * Respond to a file that has been copied.
+ *
+ * @param Drupal\file\File $file
+ *   The newly copied file entity.
+ * @param Drupal\file\File $source
+ *   The original file before the copy.
+ *
+ * @see file_copy()
+ */
+function hook_file_copy(Drupal\file\File $file, Drupal\file\File $source) {
+
+}
+
+/**
+ * Respond to a file that has been moved.
+ *
+ * @param Drupal\file\File $file
+ *   The updated file entity after the move.
+ * @param Drupal\file\File $source
+ *   The original file entity before the move.
+ *
+ * @see file_move()
+ */
+function hook_file_move(Drupal\file\File $file, Drupal\file\File $source) {
+
+}
+
+/**
+ * Act prior to file deletion.
+ *
+ * This hook is invoked when deleting a file before the file is removed from the
+ * filesystem and before its records are removed from the database.
+ *
+ * @param Drupal\file\File $file
+ *   The file that is about to be deleted.
+ *
+ * @see hook_file_delete()
+ * @see Drupal\file\FileStorageController::delete()
+ * @see upload_file_delete()
+ */
+function hook_file_predelete(Drupal\file\File $file) {
+  // Delete all information associated with the file.
+  db_delete('upload')->condition('fid', $file->fid)->execute();
+}
+
+/**
+ * Respond to file deletion.
+ *
+ * This hook is invoked after the file has been removed from
+ * the filesystem and after its records have been removed from the database.
+ *
+ * @param Drupal\file\File $file
+ *   The file that has just been deleted.
+ *
+ * @see hook_file_predelete()
+ * @see Drupal\file\FileStorageController::delete()
+ */
+function hook_file_delete(Drupal\file\File $file) {
+  // Delete all information associated with the file.
+  db_delete('upload')->condition('fid', $file->fid)->execute();
+}
+
 /**
  * Control download access to files.
  *
diff --git a/core/modules/file/file.install b/core/modules/file/file.install
index 49fc458..a226e3d 100644
--- a/core/modules/file/file.install
+++ b/core/modules/file/file.install
@@ -6,6 +6,143 @@
  */
 
 /**
+ * Implements hook_schema().
+ */
+function file_schema() {
+  $schema['file_managed'] = array(
+    'description' => 'Stores information for uploaded files.',
+    'fields' => array(
+      'fid' => array(
+        'description' => 'File ID.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'uid' => array(
+        'description' => 'The {users}.uid of the user who is associated with the file.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'filename' => array(
+        'description' => 'Name of the file with no path components. This may differ from the basename of the URI if the file is renamed to avoid overwriting an existing file.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'binary' => TRUE,
+      ),
+      'uri' => array(
+        'description' => 'The URI to access the file (either local or remote).',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'binary' => TRUE,
+      ),
+      'langcode' => array(
+        'description' => 'The {language}.langcode of this file.',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'filemime' => array(
+        'description' => "The file's MIME type.",
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'filesize' => array(
+        'description' => 'The size of the file in bytes.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'status' => array(
+        'description' => 'A field indicating the status of the file. Two status are defined in core: temporary (0) and permanent (1). Temporary files older than DRUPAL_MAXIMUM_TEMP_FILE_AGE will be removed during a cron run.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'size' => 'tiny',
+      ),
+      'timestamp' => array(
+        'description' => 'UNIX timestamp for when the file was added.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'indexes' => array(
+      'uid' => array('uid'),
+      'status' => array('status'),
+      'timestamp' => array('timestamp'),
+    ),
+    'unique keys' => array(
+      'uri' => array('uri'),
+    ),
+    'primary key' => array('fid'),
+    'foreign keys' => array(
+      'file_owner' => array(
+        'table' => 'users',
+        'columns' => array('uid' => 'uid'),
+      ),
+    ),
+  );
+
+  $schema['file_usage'] = array(
+    'description' => 'Track where a file is used.',
+    'fields' => array(
+      'fid' => array(
+        'description' => 'File ID.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'module' => array(
+        'description' => 'The name of the module that is using the file.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'type' => array(
+        'description' => 'The name of the object type in which the file is used.',
+        'type' => 'varchar',
+        'length' => 64,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'id' => array(
+        'description' => 'The primary key of the object using the file.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'count' => array(
+        'description' => 'The number of times this file is used by this object.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'primary key' => array('fid', 'type', 'id', 'module'),
+    'indexes' => array(
+      'type_id' => array('type', 'id'),
+      'fid_count' => array('fid', 'count'),
+      'fid_module' => array('fid', 'module'),
+    ),
+  );
+  return $schema;
+}
+
+/**
  * Implements hook_field_schema().
  */
 function file_field_schema($field) {
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index 6541e8d..ea6cc44 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -6,7 +6,7 @@
  */
 
 use Drupal\entity\EntityFieldQuery;
-use Drupal\Core\File\File;
+use Drupal\file\File;
 
 // Load all Field module hooks for File.
 require_once DRUPAL_ROOT . '/core/modules/file/file.field.inc';
@@ -86,6 +86,650 @@ function file_element_info() {
 }
 
 /**
+ * Implements hook_entity_info().
+ */
+function file_entity_info() {
+  return array(
+    'file' => array(
+      'label' => t('File'),
+      'base table' => 'file_managed',
+      'controller class' => 'Drupal\file\FileStorageController',
+      'entity class' => 'Drupal\file\File',
+      'entity keys' => array(
+        'id' => 'fid',
+        'label' => 'filename',
+      ),
+      'static cache' => FALSE,
+    ),
+  );
+}
+
+
+/**
+ * Loads file entities from the database.
+ *
+ * @param array|bool $fids
+ *   An array of file IDs, or FALSE to load all files.
+ * @param array $conditions
+ *   (deprecated) An associative array of conditions on the {file_managed}
+ *   table, where the keys are the database fields and the values are the
+ *   values those fields must have. Instead, it is preferable to use
+ *   Drupal\entity\EntityFieldQuery to retrieve a list of entity IDs
+ *   loadable by this function.
+ *
+ * @return array
+ *   An array of file entities, indexed by fid.
+ *
+ * @todo Remove $conditions in Drupal 8.
+ *
+ * @see hook_file_load()
+ * @see file_load()
+ * @see entity_load()
+ * @see Drupal\entity\EntityFieldQuery
+ */
+function file_load_multiple($fids = array(), array $conditions = array()) {
+  return entity_load_multiple('file', $fids, $conditions);
+}
+
+/**
+ * Loads a single file entity from the database.
+ *
+ * @param $fid
+ *   A file ID.
+ *
+ * @return Drupal\file\File
+ *   A file entity or FALSE if the file was not found.
+ *
+ * @see hook_file_load()
+ * @see file_load_multiple()
+ */
+function file_load($fid) {
+  $files = file_load_multiple(array($fid), array());
+  return reset($files);
+}
+
+/**
+ * Determines where a file is used.
+ *
+ * @param Drupal\file\File $file
+ *   A file entity.
+ *
+ * @return
+ *   A nested array with usage data. The first level is keyed by module name,
+ *   the second by object type and the third by the object id. The value
+ *   of the third level contains the usage count.
+ *
+ * @see file_usage_add()
+ * @see file_usage_delete()
+ */
+function file_usage_list(File $file) {
+  $result = db_select('file_usage', 'f')
+    ->fields('f', array('module', 'type', 'id', 'count'))
+    ->condition('fid', $file->fid)
+    ->condition('count', 0, '>')
+    ->execute();
+  $references = array();
+  foreach ($result as $usage) {
+    $references[$usage->module][$usage->type][$usage->id] = $usage->count;
+  }
+  return $references;
+}
+
+/**
+ * Records that a module is using a file.
+ *
+ * Examples:
+ * - A module that associates files with nodes, so $type would be
+ *   'node' and $id would be the node's nid. Files for all revisions are stored
+ *   within a single nid.
+ * - The User module associates an image with a user, so $type would be 'user'
+ *   and the $id would be the user's uid.
+ *
+ * @param Drupal\file\File $file
+ *   A file entity.
+ * @param $module
+ *   The name of the module using the file.
+ * @param $type
+ *   The type of the object that contains the referenced file.
+ * @param $id
+ *   The unique, numeric ID of the object containing the referenced file.
+ * @param $count
+ *   (optional) The number of references to add to the object. Defaults to 1.
+ *
+ * @see file_usage_list()
+ * @see file_usage_delete()
+ */
+function file_usage_add(File $file, $module, $type, $id, $count = 1) {
+  db_merge('file_usage')
+    ->key(array(
+      'fid' => $file->fid,
+      'module' => $module,
+      'type' => $type,
+      'id' => $id,
+    ))
+    ->fields(array('count' => $count))
+    ->expression('count', 'count + :count', array(':count' => $count))
+    ->execute();
+
+  // Make sure that a used file is permament.
+  if ($file->status != FILE_STATUS_PERMANENT) {
+    $file->status = FILE_STATUS_PERMANENT;
+    $file->save();
+  }
+}
+
+/**
+ * Removes a record to indicate that a module is no longer using a file.
+ *
+ * @param Drupal\file\File $file
+ *   A file entity.
+ * @param $module
+ *   The name of the module using the file.
+ * @param $type
+ *   (optional) The type of the object that contains the referenced file. May
+ *   be omitted if all module references to a file are being deleted.
+ * @param $id
+ *   (optional) The unique, numeric ID of the object containing the referenced
+ *   file. May be omitted if all module references to a file are being deleted.
+ * @param $count
+ *   (optional) The number of references to delete from the object. Defaults to
+ *   1. 0 may be specified to delete all references to the file within a
+ *   specific object.
+ *
+ * @see file_usage_add()
+ * @see file_usage_list()
+ */
+function file_usage_delete(File $file, $module, $type = NULL, $id = NULL, $count = 1) {
+  // Delete rows that have a exact or less value to prevent empty rows.
+  $query = db_delete('file_usage')
+    ->condition('module', $module)
+    ->condition('fid', $file->fid);
+  if ($type && $id) {
+    $query
+      ->condition('type', $type)
+      ->condition('id', $id);
+  }
+  if ($count) {
+    $query->condition('count', $count, '<=');
+  }
+  $result = $query->execute();
+
+  // If the row has more than the specified count decrement it by that number.
+  if (!$result && $count > 0) {
+    $query = db_update('file_usage')
+      ->condition('module', $module)
+      ->condition('fid', $file->fid);
+    if ($type && $id) {
+      $query
+        ->condition('type', $type)
+        ->condition('id', $id);
+    }
+    $query->expression('count', 'count - :count', array(':count' => $count));
+    $query->execute();
+  }
+
+  // If there are no more remaining usages of this file, mark it as temporary,
+  // which result in a delete through system_cron().
+  $usage = file_usage_list($file);
+  if (empty($usage)) {
+    $file->status = 0;
+    $file->save();
+  }
+}
+
+/**
+ * Copies a file to a new location and adds a file record to the database.
+ *
+ * This function should be used when manipulating files that have records
+ * stored in the database. This is a powerful function that in many ways
+ * performs like an advanced version of copy().
+ * - Checks if $source and $destination are valid and readable/writable.
+ * - Checks that $source is not equal to $destination; if they are an error
+ *   is reported.
+ * - If file already exists in $destination either the call will error out,
+ *   replace the file or rename the file based on the $replace parameter.
+ * - Adds the new file to the files database. If the source file is a
+ *   temporary file, the resulting file will also be a temporary file. See
+ *   file_save_upload() for details on temporary files.
+ *
+ * @param Drupal\file\File $source
+ *   A file entity.
+ * @param $destination
+ *   A string containing the destination that $source should be copied to.
+ *   This must be a stream wrapper URI.
+ * @param $replace
+ *   Replace behavior when the destination file already exists:
+ *   - FILE_EXISTS_REPLACE - Replace the existing file. If a managed file with
+ *       the destination name exists then its database entry will be updated. If
+ *       no database entry is found then a new one will be created.
+ *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
+ *       unique.
+ *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
+ *
+ * @return
+ *   File object if the copy is successful, or FALSE in the event of an error.
+ *
+ * @see file_unmanaged_copy()
+ * @see hook_file_copy()
+ */
+function file_copy(File $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
+  if (!file_valid_uri($destination)) {
+    if (($realpath = drupal_realpath($source->uri)) !== FALSE) {
+      watchdog('file', 'File %file (%realpath) could not be copied because the destination %destination is invalid. This is often caused by improper use of file_copy() or a missing stream wrapper.', array('%file' => $source->uri, '%realpath' => $realpath, '%destination' => $destination));
+    }
+    else {
+      watchdog('file', 'File %file could not be copied because the destination %destination is invalid. This is often caused by improper use of file_copy() or a missing stream wrapper.', array('%file' => $source->uri, '%destination' => $destination));
+    }
+    drupal_set_message(t('The specified file %file could not be copied because the destination is invalid. More information is available in the system log.', array('%file' => $source->uri)), 'error');
+    return FALSE;
+  }
+
+  if ($uri = file_unmanaged_copy($source->uri, $destination, $replace)) {
+    $file = clone $source;
+    $file->fid = NULL;
+    $file->uri = $uri;
+    $file->filename = drupal_basename($uri);
+    // If we are replacing an existing file re-use its database record.
+    if ($replace == FILE_EXISTS_REPLACE) {
+      $existing_files = file_load_multiple(array(), array('uri' => $uri));
+      if (count($existing_files)) {
+        $existing = reset($existing_files);
+        $file->fid = $existing->fid;
+        $file->filename = $existing->filename;
+      }
+    }
+    // If we are renaming around an existing file (rather than a directory),
+    // use its basename for the filename.
+    elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
+      $file->filename = drupal_basename($destination);
+    }
+
+    $file->save();
+
+    // Inform modules that the file has been copied.
+    module_invoke_all('file_copy', $file, $source);
+
+    return $file;
+  }
+  return FALSE;
+}
+
+
+/**
+ * Moves a file to a new location and update the file's database entry.
+ *
+ * Moving a file is performed by copying the file to the new location and then
+ * deleting the original.
+ * - Checks if $source and $destination are valid and readable/writable.
+ * - Performs a file move if $source is not equal to $destination.
+ * - If file already exists in $destination either the call will error out,
+ *   replace the file or rename the file based on the $replace parameter.
+ * - Adds the new file to the files database.
+ *
+ * @param Drupal\file\File $source
+ *   A file entity.
+ * @param $destination
+ *   A string containing the destination that $source should be moved to.
+ *   This must be a stream wrapper URI.
+ * @param $replace
+ *   Replace behavior when the destination file already exists:
+ *   - FILE_EXISTS_REPLACE - Replace the existing file. If a managed file with
+ *       the destination name exists then its database entry will be updated and
+ *       $source->delete() called after invoking hook_file_move().
+ *       If no database entry is found then the source files record will be
+ *       updated.
+ *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
+ *       unique.
+ *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
+ *
+ * @return Drupal\file\File
+ *   Resulting file entity for success, or FALSE in the event of an error.
+ *
+ * @see file_unmanaged_move()
+ * @see hook_file_move()
+ */
+function file_move(File $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
+  if (!file_valid_uri($destination)) {
+    if (($realpath = drupal_realpath($source->uri)) !== FALSE) {
+      watchdog('file', 'File %file (%realpath) could not be moved because the destination %destination is invalid. This may be caused by improper use of file_move() or a missing stream wrapper.', array('%file' => $source->uri, '%realpath' => $realpath, '%destination' => $destination));
+    }
+    else {
+      watchdog('file', 'File %file could not be moved because the destination %destination is invalid. This may be caused by improper use of file_move() or a missing stream wrapper.', array('%file' => $source->uri, '%destination' => $destination));
+    }
+    drupal_set_message(t('The specified file %file could not be moved because the destination is invalid. More information is available in the system log.', array('%file' => $source->uri)), 'error');
+    return FALSE;
+  }
+
+  if ($uri = file_unmanaged_move($source->uri, $destination, $replace)) {
+    $delete_source = FALSE;
+
+    $file = clone $source;
+    $file->uri = $uri;
+    // If we are replacing an existing file re-use its database record.
+    if ($replace == FILE_EXISTS_REPLACE) {
+      $existing_files = file_load_multiple(array(), array('uri' => $uri));
+      if (count($existing_files)) {
+        $existing = reset($existing_files);
+        $delete_source = TRUE;
+        $file->fid = $existing->fid;
+      }
+    }
+    // If we are renaming around an existing file (rather than a directory),
+    // use its basename for the filename.
+    elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
+      $file->filename = drupal_basename($destination);
+    }
+
+    $file->save();
+
+    // Inform modules that the file has been moved.
+    module_invoke_all('file_move', $file, $source);
+
+    // Delete the original if it's not in use elsewhere.
+    if ($delete_source && !file_usage_list($source)) {
+      $source->delete();
+    }
+
+    return $file;
+  }
+  return FALSE;
+}
+
+
+/**
+ * Checks that a file meets the criteria specified by the validators.
+ *
+ * After executing the validator callbacks specified hook_file_validate() will
+ * also be called to allow other modules to report errors about the file.
+ *
+ * @param Drupal\file\File $file
+ *   A file entity.
+ * @param $validators
+ *   An optional, associative array of callback functions used to validate the
+ *   file. The keys are function names and the values arrays of callback
+ *   parameters which will be passed in after the file entity. The
+ *   functions should return an array of error messages; an empty array
+ *   indicates that the file passed validation. The functions will be called in
+ *   the order specified.
+ *
+ * @return
+ *   An array containing validation error messages.
+ *
+ * @see hook_file_validate()
+ */
+function file_validate(File $file, $validators = array()) {
+  // Call the validation functions specified by this function's caller.
+  $errors = array();
+  foreach ($validators as $function => $args) {
+    if (function_exists($function)) {
+      array_unshift($args, $file);
+      $errors = array_merge($errors, call_user_func_array($function, $args));
+    }
+  }
+
+  // Let other modules perform validation on the new file.
+  return array_merge($errors, module_invoke_all('file_validate', $file));
+}
+
+/**
+ * Checks for files with names longer than can be stored in the database.
+ *
+ * @param Drupal\file\File $file
+ *   A file entity.
+ *
+ * @return
+ *   An array. If the file name is too long, it will contain an error message.
+ */
+function file_validate_name_length(File $file) {
+  $errors = array();
+
+  if (empty($file->filename)) {
+    $errors[] = t("The file's name is empty. Please give a name to the file.");
+  }
+  if (strlen($file->filename) > 240) {
+    $errors[] = t("The file's name exceeds the 240 characters limit. Please rename the file and try again.");
+  }
+  return $errors;
+}
+
+/**
+ * Checks that the filename ends with an allowed extension.
+ *
+ * @param Drupal\file\File $file
+ *   A file entity.
+ * @param $extensions
+ *   A string with a space separated list of allowed extensions.
+ *
+ * @return
+ *   An array. If the file extension is not allowed, it will contain an error
+ *   message.
+ *
+ * @see hook_file_validate()
+ */
+function file_validate_extensions(File $file, $extensions) {
+  $errors = array();
+
+  $regex = '/\.(' . preg_replace('/ +/', '|', preg_quote($extensions)) . ')$/i';
+  if (!preg_match($regex, $file->filename)) {
+    $errors[] = t('Only files with the following extensions are allowed: %files-allowed.', array('%files-allowed' => $extensions));
+  }
+  return $errors;
+}
+
+/**
+ * Checks that the file's size is below certain limits.
+ *
+ * This check is not enforced for the user #1.
+ *
+ * @param Drupal\file\File $file
+ *   A file entity.
+ * @param $file_limit
+ *   An integer specifying the maximum file size in bytes. Zero indicates that
+ *   no limit should be enforced.
+ * @param $user_limit
+ *   An integer specifying the maximum number of bytes the user is allowed.
+ *   Zero indicates that no limit should be enforced.
+ *
+ * @return
+ *   An array. If the file size exceeds limits, it will contain an error
+ *   message.
+ *
+ * @see hook_file_validate()
+ */
+function file_validate_size(File $file, $file_limit = 0, $user_limit = 0) {
+  global $user;
+
+  $errors = array();
+
+  // Bypass validation for uid  = 1.
+  if ($user->uid != 1) {
+    if ($file_limit && $file->filesize > $file_limit) {
+      $errors[] = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size($file->filesize), '%maxsize' => format_size($file_limit)));
+    }
+
+    // Save a query by only calling file_space_used() when a limit is provided.
+    if ($user_limit && (file_space_used($user->uid) + $file->filesize) > $user_limit) {
+      $errors[] = t('The file is %filesize which would exceed your disk quota of %quota.', array('%filesize' => format_size($file->filesize), '%quota' => format_size($user_limit)));
+    }
+  }
+  return $errors;
+}
+
+/**
+ * Checks that the file is recognized by image_get_info() as an image.
+ *
+ * @param Drupal\file\File $file
+ *   A file entity.
+ *
+ * @return
+ *   An array. If the file is not an image, it will contain an error message.
+ *
+ * @see hook_file_validate()
+ */
+function file_validate_is_image(File $file) {
+  $errors = array();
+
+  $info = image_get_info($file->uri);
+  if (!$info || empty($info['extension'])) {
+    $errors[] = t('Only JPEG, PNG and GIF images are allowed.');
+  }
+
+  return $errors;
+}
+
+/**
+ * Verifies that image dimensions are within the specified maximum and minimum.
+ *
+ * Non-image files will be ignored. If a image toolkit is available the image
+ * will be scaled to fit within the desired maximum dimensions.
+ *
+ * @param Drupal\file\File $file
+ *   A file entity. This function may resize the file affecting its size.
+ * @param $maximum_dimensions
+ *   An optional string in the form WIDTHxHEIGHT e.g. '640x480' or '85x85'. If
+ *   an image toolkit is installed the image will be resized down to these
+ *   dimensions. A value of 0 indicates no restriction on size, so resizing
+ *   will be attempted.
+ * @param $minimum_dimensions
+ *   An optional string in the form WIDTHxHEIGHT. This will check that the
+ *   image meets a minimum size. A value of 0 indicates no restriction.
+ *
+ * @return
+ *   An array. If the file is an image and did not meet the requirements, it
+ *   will contain an error message.
+ *
+ * @see hook_file_validate()
+ */
+function file_validate_image_resolution(File $file, $maximum_dimensions = 0, $minimum_dimensions = 0) {
+  $errors = array();
+
+  // Check first that the file is an image.
+  if ($info = image_get_info($file->uri)) {
+    if ($maximum_dimensions) {
+      // Check that it is smaller than the given dimensions.
+      list($width, $height) = explode('x', $maximum_dimensions);
+      if ($info['width'] > $width || $info['height'] > $height) {
+        // Try to resize the image to fit the dimensions.
+        if ($image = image_load($file->uri)) {
+          image_scale($image, $width, $height);
+          image_save($image);
+          $file->filesize = $image->info['file_size'];
+          drupal_set_message(t('The image was resized to fit within the maximum allowed dimensions of %dimensions pixels.', array('%dimensions' => $maximum_dimensions)));
+        }
+        else {
+          $errors[] = t('The image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => $maximum_dimensions));
+        }
+      }
+    }
+
+    if ($minimum_dimensions) {
+      // Check that it is larger than the given dimensions.
+      list($width, $height) = explode('x', $minimum_dimensions);
+      if ($info['width'] < $width || $info['height'] < $height) {
+        $errors[] = t('The image is too small; the minimum dimensions are %dimensions pixels.', array('%dimensions' => $minimum_dimensions));
+      }
+    }
+  }
+
+  return $errors;
+}
+
+/**
+ * Saves a file to the specified destination and creates a database entry.
+ *
+ * @param $data
+ *   A string containing the contents of the file.
+ * @param $destination
+ *   A string containing the destination URI. This must be a stream wrapper URI.
+ *   If no value is provided, a randomized name will be generated and the file
+ *   will be saved using Drupal's default files scheme, usually "public://".
+ * @param $replace
+ *   Replace behavior when the destination file already exists:
+ *   - FILE_EXISTS_REPLACE - Replace the existing file. If a managed file with
+ *       the destination name exists then its database entry will be updated. If
+ *       no database entry is found then a new one will be created.
+ *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
+ *       unique.
+ *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
+ *
+ * @return Drupal\file\File
+ *   A file entity, or FALSE on error.
+ *
+ * @see file_unmanaged_save_data()
+ */
+function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
+  global $user;
+
+  if (empty($destination)) {
+    $destination = file_default_scheme() . '://';
+  }
+  if (!file_valid_uri($destination)) {
+    watchdog('file', 'The data could not be saved because the destination %destination is invalid. This may be caused by improper use of file_save_data() or a missing stream wrapper.', array('%destination' => $destination));
+    drupal_set_message(t('The data could not be saved because the destination is invalid. More information is available in the system log.'), 'error');
+    return FALSE;
+  }
+
+  if ($uri = file_unmanaged_save_data($data, $destination, $replace)) {
+    // Create a file entity.
+    $file = entity_create('file', array(
+      'uri' => $uri,
+      'uid' => $user->uid,
+      'status' => FILE_STATUS_PERMANENT,
+    ));
+    // If we are replacing an existing file re-use its database record.
+    if ($replace == FILE_EXISTS_REPLACE) {
+      $existing_files = file_load_multiple(array(), array('uri' => $uri));
+      if (count($existing_files)) {
+        $existing = reset($existing_files);
+        $file->fid = $existing->fid;
+        $file->filename = $existing->filename;
+      }
+    }
+    // If we are renaming around an existing file (rather than a directory),
+    // use its basename for the filename.
+    elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
+      $file->filename = drupal_basename($destination);
+    }
+
+    $file->save();
+    return $file;
+  }
+  return FALSE;
+}
+
+
+/**
+ * Examines a file entity and returns appropriate content headers for download.
+ *
+ * @param Drupal\file\File $file
+ *   A file entity.
+ *
+ * @return
+ *   An associative array of headers, as expected by
+ *   \Symfony\Component\HttpFoundation\StreamedResponse.
+ */
+function file_get_content_headers(File $file) {
+  $name = mime_header_encode($file->filename);
+  $type = mime_header_encode($file->filemime);
+  // Serve images, text, and flash content for display rather than download.
+  $inline_types = variable_get('file_inline_types', array('^text/', '^image/', 'flash$'));
+  $disposition = 'attachment';
+  foreach ($inline_types as $inline_type) {
+    // Exclamation marks are used as delimiters to avoid escaping slashes.
+    if (preg_match('!' . $inline_type . '!', $file->filemime)) {
+      $disposition = 'inline';
+    }
+  }
+
+  return array(
+    'Content-Type' => $type . '; name="' . $name . '"',
+    'Content-Length' => $file->filesize,
+    'Content-Disposition' => $disposition . '; filename="' . $name . '"',
+    'Cache-Control' => 'private',
+  );
+}
+
+/**
  * Implements hook_theme().
  */
 function file_theme() {
@@ -226,6 +870,35 @@ function file_file_download($uri, $field_type = 'file') {
 }
 
 /**
+ * Implements file_cron()
+ */
+function file_cron() {
+  // Remove temporary files that are older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
+  // Use separate placeholders for the status to avoid a bug in some versions
+  // of PHP. See http://drupal.org/node/352956.
+  $result = db_query('SELECT fid FROM {file_managed} WHERE status <> :permanent AND timestamp < :timestamp', array(
+    ':permanent' => FILE_STATUS_PERMANENT,
+    ':timestamp' => REQUEST_TIME - DRUPAL_MAXIMUM_TEMP_FILE_AGE
+  ));
+  foreach ($result as $row) {
+    if ($file = file_load($row->fid)) {
+      $references = file_usage_list($file);
+      if (empty($references)) {
+        if (file_exists($file->uri)) {
+          $file->delete();
+        }
+        else {
+          watchdog('file system', 'Could not delete temporary file "%path" during garbage collection', array('%path' => $file->uri), WATCHDOG_ERROR);
+        }
+      }
+      else {
+        watchdog('file system', 'Did not delete temporary file "%path" during garbage collection because it is in use by the following modules: %modules.', array('%path' => $file->uri, '%modules' => implode(', ', array_keys($references))), WATCHDOG_INFO);
+      }
+    }
+  }
+}
+
+/**
  * Ajax callback: Processes file uploads and deletions.
  *
  * This rebuilds the form element for a particular field item. As long as the
@@ -782,7 +1455,7 @@ function theme_file_icon($variables) {
 /**
  * Creates a URL to the icon for a file entity.
  *
- * @param Drupal\Core\File\File $file
+ * @param Drupal\file\File $file
  *   A file entity.
  * @param $icon_directory
  *   (optional) A path to a directory of icons to be used for files. Defaults to
@@ -801,7 +1474,7 @@ function file_icon_url(File $file, $icon_directory = NULL) {
 /**
  * Creates a path to the icon for a file entity.
  *
- * @param Drupal\Core\File\File $file
+ * @param Drupal\file\File $file
  *   A file entity.
  * @param $icon_directory
  *   (optional) A path to a directory of icons to be used for files. Defaults to
@@ -854,7 +1527,7 @@ function file_icon_path(File $file, $icon_directory = NULL) {
 /**
  * Determines the generic icon MIME package based on a file's MIME type.
  *
- * @param Drupal\Core\File\File $file
+ * @param Drupal\file\File $file
  *   A file entity.
  *
  * @return
@@ -986,7 +1659,7 @@ function file_icon_map(File $file) {
 /**
  * Retrieves a list of references to a file.
  *
- * @param Drupal\Core\File\File $file
+ * @param Drupal\file\File $file
  *   A file entity.
  * @param $field
  *   (optional) A field array to be used for this check. If given, limits the
diff --git a/core/lib/Drupal/Core/File/File.php b/core/modules/file/lib/Drupal/file/File.php
similarity index 95%
rename from core/lib/Drupal/Core/File/File.php
rename to core/modules/file/lib/Drupal/file/File.php
index b35f5ee..68865c5 100644
--- a/core/lib/Drupal/Core/File/File.php
+++ b/core/modules/file/lib/Drupal/file/File.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Definition of Drupal\Core\File\File.
+ * Definition of Drupal\file\File.
  */
 
-namespace Drupal\Core\File;
+namespace Drupal\file;
 
 use Drupal\entity\Entity;
 
diff --git a/core/lib/Drupal/Core/File/FileStorageController.php b/core/modules/file/lib/Drupal/file/FileStorageController.php
similarity index 95%
rename from core/lib/Drupal/Core/File/FileStorageController.php
rename to core/modules/file/lib/Drupal/file/FileStorageController.php
index 940e1fd..356e5c4 100644
--- a/core/lib/Drupal/Core/File/FileStorageController.php
+++ b/core/modules/file/lib/Drupal/file/FileStorageController.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Definition of Drupal\Core\File\FileStorageController.
+ * Definition of Drupal\file\FileStorageController.
  */
 
-namespace Drupal\Core\File;
+namespace Drupal\file;
 
 use Drupal\entity\DatabaseStorageController;
 use Drupal\entity\EntityInterface;
diff --git a/core/modules/file/lib/Drupal/file/Tests/CopyTest.php b/core/modules/file/lib/Drupal/file/Tests/CopyTest.php
new file mode 100644
index 0000000..7f20c9f
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/CopyTest.php
@@ -0,0 +1,153 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\CopyTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ * Copy related tests.
+ */
+class CopyTest extends FileManagedTestBase {
+  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));
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/DeleteTest.php b/core/modules/file/lib/Drupal/file/Tests/DeleteTest.php
new file mode 100644
index 0000000..be2f8a4
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/DeleteTest.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\DeleteTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ * Deletion related tests.
+ */
+class DeleteTest extends FileManagedTestBase {
+  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.'));
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/DownloadTest.php b/core/modules/file/lib/Drupal/file/Tests/DownloadTest.php
new file mode 100644
index 0000000..1294b8d
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/DownloadTest.php
@@ -0,0 +1,152 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\DownloadTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ * Tests for download/file transfer functions.
+ */
+class DownloadTest extends FileManagedTestBase {
+  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();
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileManagedTestBase.php b/core/modules/file/lib/Drupal/file/Tests/FileManagedTestBase.php
new file mode 100644
index 0000000..1b2d980
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/FileManagedTestBase.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\FileManagedTestBase.
+ */
+
+namespace Drupal\file\Tests;
+
+use Drupal\system\Tests\File\FileTestBase;
+use \stdClass;
+
+/**
+ * Base class for file tests that use the file_test module to test uploads and
+ * hooks.
+ */
+class FileManagedTestBase extends FileTestBase {
+  function setUp() {
+    // Install file_test module
+    parent::setUp('file_test', 'file');
+    // 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.
+   * @param $message
+   *   Optional translated string message.
+   */
+  function assertFileHookCalled($hook, $expected_count = 1, $message = NULL) {
+    $actual_count = count(file_test_get_calls($hook));
+
+    if (!isset($message)) {
+      if ($actual_count == $expected_count) {
+        $message = t('hook_file_@name was called correctly.', array('@name' => $hook));
+      }
+      elseif ($expected_count == 0) {
+        $message = format_plural($actual_count, 'hook_file_@name was not expected to be called but was actually called once.', 'hook_file_@name was not expected to be called but was actually called @count times.', array('@name' => $hook, '@count' => $actual_count));
+      }
+      else {
+        $message = t('hook_file_@name was expected to be called %expected times but was called %actual times.', array('@name' => $hook, '%expected' => $expected_count, '%actual' => $actual_count));
+      }
+    }
+    $this->assertEqual($actual_count, $expected_count, $message);
+  }
+
+  /**
+   * Create a file and save it to the files table and assert that it occurs
+   * correctly.
+   *
+   * @param $filepath
+   *   Optional string specifying the file path. If none is provided then a
+   *   randomly named file will be created in the site's files directory.
+   * @param $contents
+   *   Optional contents to save into the file. If a NULL value is provided an
+   *   arbitrary string will be used.
+   * @param $scheme
+   *   Optional string indicating the stream scheme to use. Drupal core includes
+   *   public, private, and temporary. The public wrapper is the default.
+   * @return
+   *   File object.
+   */
+  function createFile($filepath = NULL, $contents = NULL, $scheme = NULL) {
+    $file = new stdClass();
+    $file->uri = $this->createUri($filepath, $contents, $scheme);
+    $file->filename = drupal_basename($file->uri);
+    $file->filemime = 'text/plain';
+    $file->uid = 1;
+    $file->timestamp = REQUEST_TIME;
+    $file->filesize = filesize($file->uri);
+    $file->status = 0;
+    // Write the record directly rather than using the API so we don't invoke
+    // the hooks.
+    $this->assertNotIdentical(drupal_write_record('file_managed', $file), FALSE, t('The file was added to the database.'), 'Create test file');
+
+    return entity_create('file', (array) $file);
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/LoadTest.php b/core/modules/file/lib/Drupal/file/Tests/LoadTest.php
new file mode 100644
index 0000000..1f152e7
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/LoadTest.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\LoadTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ * Tests the file_load() function.
+ */
+class LoadTest extends FileManagedTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'File loading',
+      'description' => 'Tests the file_load() function.',
+      'group' => 'File API',
+    );
+  }
+
+  /**
+   * Try to load a non-existent file by fid.
+   */
+  function testLoadMissingFid() {
+    $this->assertFalse(file_load(-1), t("Try to load an invalid fid fails."));
+    $this->assertFileHooksCalled(array());
+  }
+
+  /**
+   * Try to load a non-existent file by URI.
+   */
+  function testLoadMissingFilepath() {
+    $files = file_load_multiple(array(), array('uri' => 'foobar://misc/druplicon.png'));
+    $this->assertFalse(reset($files), t("Try to load a file that doesn't exist in the database fails."));
+    $this->assertFileHooksCalled(array());
+  }
+
+  /**
+   * Try to load a non-existent file by status.
+   */
+  function testLoadInvalidStatus() {
+    $files = file_load_multiple(array(), array('status' => -99));
+    $this->assertFalse(reset($files), t("Trying to load a file with an invalid status fails."));
+    $this->assertFileHooksCalled(array());
+  }
+
+  /**
+   * Load a single file and ensure that the correct values are returned.
+   */
+  function testSingleValues() {
+    // Create a new file entity from scratch so we know the values.
+    $file = $this->createFile('druplicon.txt', NULL, 'public');
+
+    $by_fid_file = file_load($file->fid);
+    $this->assertFileHookCalled('load');
+    $this->assertTrue(is_object($by_fid_file), t('file_load() returned an object.'));
+    $this->assertEqual($by_fid_file->fid, $file->fid, t("Loading by fid got the same fid."), 'File');
+    $this->assertEqual($by_fid_file->uri, $file->uri, t("Loading by fid got the correct filepath."), 'File');
+    $this->assertEqual($by_fid_file->filename, $file->filename, t("Loading by fid got the correct filename."), 'File');
+    $this->assertEqual($by_fid_file->filemime, $file->filemime, t("Loading by fid got the correct MIME type."), 'File');
+    $this->assertEqual($by_fid_file->status, $file->status, t("Loading by fid got the correct status."), 'File');
+    $this->assertTrue($by_fid_file->file_test['loaded'], t('file_test_file_load() was able to modify the file during load.'));
+  }
+
+  /**
+   * This will test loading file data from the database.
+   */
+  function testMultiple() {
+    // Create a new file entity.
+    $file = $this->createFile('druplicon.txt', NULL, 'public');
+
+    // Load by path.
+    file_test_reset();
+    $by_path_files = file_load_multiple(array(), array('uri' => $file->uri));
+    $this->assertFileHookCalled('load');
+    $this->assertEqual(1, count($by_path_files), t('file_load_multiple() returned an array of the correct size.'));
+    $by_path_file = reset($by_path_files);
+    $this->assertTrue($by_path_file->file_test['loaded'], t('file_test_file_load() was able to modify the file during load.'));
+    $this->assertEqual($by_path_file->fid, $file->fid, t("Loading by filepath got the correct fid."), 'File');
+
+    // Load by fid.
+    file_test_reset();
+    $by_fid_files = file_load_multiple(array($file->fid), array());
+    $this->assertFileHookCalled('load');
+    $this->assertEqual(1, count($by_fid_files), t('file_load_multiple() returned an array of the correct size.'));
+    $by_fid_file = reset($by_fid_files);
+    $this->assertTrue($by_fid_file->file_test['loaded'], t('file_test_file_load() was able to modify the file during load.'));
+    $this->assertEqual($by_fid_file->uri, $file->uri, t("Loading by fid got the correct filepath."), 'File');
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/MoveTest.php b/core/modules/file/lib/Drupal/file/Tests/MoveTest.php
new file mode 100644
index 0000000..15868b1
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/MoveTest.php
@@ -0,0 +1,168 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\MoveTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ * Move related tests
+ */
+class MoveTest extends FileManagedTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'File moving',
+      'description' => 'Tests the file move function.',
+      'group' => 'File API',
+    );
+  }
+
+  /**
+   * Move a normal file.
+   */
+  function testNormal() {
+    $contents = $this->randomName(10);
+    $source = $this->createFile(NULL, $contents);
+    $desired_filepath = 'public://' . $this->randomName();
+
+    // Clone the object so we don't have to worry about the function changing
+    // our reference copy.
+    $result = file_move(clone $source, $desired_filepath, FILE_EXISTS_ERROR);
+
+    // Check the return status and that the contents changed.
+    $this->assertTrue($result, t('File moved successfully.'));
+    $this->assertFalse(file_exists($source->uri));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file correctly written.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('move', 'load', 'update'));
+
+    // Make sure we got the same file back.
+    $this->assertEqual($source->fid, $result->fid, t("Source file id's' %fid is unchanged after move.", array('%fid' => $source->fid)));
+
+    // Reload the file from the database and check that the changes were
+    // actually saved.
+    $loaded_file = file_load($result->fid, TRUE);
+    $this->assertTrue($loaded_file, t('File can be loaded from the database.'));
+    $this->assertFileUnchanged($result, $loaded_file);
+  }
+
+  /**
+   * Test renaming when moving onto 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_move(clone $source, $target->uri, FILE_EXISTS_RENAME);
+
+    // Check the return status and that the contents changed.
+    $this->assertTrue($result, t('File moved successfully.'));
+    $this->assertFalse(file_exists($source->uri));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file correctly written.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('move', 'load', 'update'));
+
+    // Compare the returned value to what made it into the database.
+    $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
+    // The target file should not have been altered.
+    $this->assertFileUnchanged($target, file_load($target->fid, TRUE));
+    // Make sure we end up with two distinct files afterwards.
+    $this->assertDifferentFile($target, $result);
+
+    // Compare the source and results.
+    $loaded_source = file_load($source->fid, TRUE);
+    $this->assertEqual($loaded_source->fid, $result->fid, t("Returned file's id matches the source."));
+    $this->assertNotEqual($loaded_source->uri, $source->uri, t("Returned file path has changed from the original."));
+  }
+
+  /**
+   * Test replacement when moving onto 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_move(clone $source, $target->uri, FILE_EXISTS_REPLACE);
+
+    // Look at the results.
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were overwritten.'));
+    $this->assertFalse(file_exists($source->uri));
+    $this->assertTrue($result, t('File moved successfully.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('move', 'update', 'delete', 'load'));
+
+    // Reload the file from the database and check that the changes were
+    // actually saved.
+    $loaded_result = file_load($result->fid, TRUE);
+    $this->assertFileUnchanged($result, $loaded_result);
+    // Check that target was re-used.
+    $this->assertSameFile($target, $loaded_result);
+    // Source and result should be totally different.
+    $this->assertDifferentFile($source, $loaded_result);
+  }
+
+  /**
+   * Test replacement when moving onto itself.
+   */
+  function testExistingReplaceSelf() {
+    // Setup a file to overwrite.
+    $contents = $this->randomName(10);
+    $source = $this->createFile(NULL, $contents);
+
+    // Copy the file over itself. Clone the object so we don't have to worry
+    // about the function changing our reference copy.
+    $result = file_move(clone $source, $source->uri, FILE_EXISTS_REPLACE);
+    $this->assertFalse($result, t('File move failed.'));
+    $this->assertEqual($contents, file_get_contents($source->uri), t('Contents of file were not altered.'));
+
+    // Check that no hooks were called while failing.
+    $this->assertFileHooksCalled(array());
+
+    // Load the file from the database and make sure it is identical to what
+    // was returned.
+    $this->assertFileUnchanged($source, file_load($source->fid, TRUE));
+  }
+
+  /**
+   * Test that moving onto 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_move(clone $source, $target->uri, FILE_EXISTS_ERROR);
+
+    // Check the return status and that the contents did not change.
+    $this->assertFalse($result, t('File move failed.'));
+    $this->assertTrue(file_exists($source->uri));
+    $this->assertEqual($contents, file_get_contents($target->uri), t('Contents of file were not altered.'));
+
+    // Check that no hooks were called while failing.
+    $this->assertFileHooksCalled(array());
+
+    // Load the file from the database and make sure it is identical to what
+    // was returned.
+    $this->assertFileUnchanged($source, file_load($source->fid, TRUE));
+    $this->assertFileUnchanged($target, file_load($target->fid, TRUE));
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/RemoteFileSaveUploadTest.php b/core/modules/file/lib/Drupal/file/Tests/RemoteFileSaveUploadTest.php
new file mode 100644
index 0000000..74ef49c
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/RemoteFileSaveUploadTest.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\RemoteFileSaveUploadTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ * Tests the file_save_upload() function on remote filesystems.
+ */
+class RemoteFileSaveUploadTest extends SaveUploadTest {
+  public static function getInfo() {
+    $info = parent::getInfo();
+    $info['group'] = 'File API (remote)';
+    return $info;
+  }
+
+  function setUp() {
+    parent::setUp('file_test');
+    variable_set('file_default_scheme', 'dummy-remote');
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/SaveDataTest.php b/core/modules/file/lib/Drupal/file/Tests/SaveDataTest.php
new file mode 100644
index 0000000..ecdb201
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/SaveDataTest.php
@@ -0,0 +1,142 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\SaveDataTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ * Tests the file_save_data() function.
+ */
+class SaveDataTest extends FileManagedTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'File save data',
+      'description' => 'Tests the file save data function.',
+      'group' => 'File API',
+    );
+  }
+
+  /**
+   * Test the file_save_data() function when no filename is provided.
+   */
+  function testWithoutFilename() {
+    $contents = $this->randomName(8);
+
+    $result = file_save_data($contents);
+    $this->assertTrue($result, t('Unnamed file saved correctly.'));
+
+    $this->assertEqual(file_default_scheme(), file_uri_scheme($result->uri), t("File was placed in Drupal's files directory."));
+    $this->assertEqual($result->filename, drupal_basename($result->uri), t("Filename was set to the file's basename."));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of the file are correct.'));
+    $this->assertEqual($result->filemime, 'application/octet-stream', t('A MIME type was set.'));
+    $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('insert'));
+
+    // Verify that what was returned is what's in the database.
+    $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
+  }
+
+  /**
+   * Test the file_save_data() function when a filename is provided.
+   */
+  function testWithFilename() {
+    $contents = $this->randomName(8);
+
+    // Using filename with non-latin characters.
+    $filename = 'Текстовый файл.txt';
+
+    $result = file_save_data($contents, 'public://' . $filename);
+    $this->assertTrue($result, t('Unnamed file saved correctly.'));
+
+    $this->assertEqual('public', file_uri_scheme($result->uri), t("File was placed in Drupal's files directory."));
+    $this->assertEqual($filename, drupal_basename($result->uri), t('File was named correctly.'));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of the file are correct.'));
+    $this->assertEqual($result->filemime, 'text/plain', t('A MIME type was set.'));
+    $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('insert'));
+
+    // Verify that what was returned is what's in the database.
+    $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
+  }
+
+  /**
+   * Test file_save_data() when renaming around an existing file.
+   */
+  function testExistingRename() {
+    // Setup a file to overwrite.
+    $existing = $this->createFile();
+    $contents = $this->randomName(8);
+
+    $result = file_save_data($contents, $existing->uri, FILE_EXISTS_RENAME);
+    $this->assertTrue($result, t("File saved successfully."));
+
+    $this->assertEqual('public', file_uri_scheme($result->uri), t("File was placed in Drupal's files directory."));
+    $this->assertEqual($result->filename, $existing->filename, t("Filename was set to the basename of the source, rather than that of the renamed file."));
+    $this->assertEqual($contents, file_get_contents($result->uri), t("Contents of the file are correct."));
+    $this->assertEqual($result->filemime, 'application/octet-stream', t("A MIME type was set."));
+    $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('insert'));
+
+    // Ensure that the existing file wasn't overwritten.
+    $this->assertDifferentFile($existing, $result);
+    $this->assertFileUnchanged($existing, file_load($existing->fid, TRUE));
+
+    // Verify that was returned is what's in the database.
+    $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
+  }
+
+  /**
+   * Test file_save_data() when replacing an existing file.
+   */
+  function testExistingReplace() {
+    // Setup a file to overwrite.
+    $existing = $this->createFile();
+    $contents = $this->randomName(8);
+
+    $result = file_save_data($contents, $existing->uri, FILE_EXISTS_REPLACE);
+    $this->assertTrue($result, t('File saved successfully.'));
+
+    $this->assertEqual('public', file_uri_scheme($result->uri), t("File was placed in Drupal's files directory."));
+    $this->assertEqual($result->filename, $existing->filename, t('Filename was set to the basename of the existing file, rather than preserving the original name.'));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of the file are correct.'));
+    $this->assertEqual($result->filemime, 'application/octet-stream', t('A MIME type was set.'));
+    $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('load', 'update'));
+
+    // Verify that the existing file was re-used.
+    $this->assertSameFile($existing, $result);
+
+    // Verify that what was returned is what's in the database.
+    $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
+  }
+
+  /**
+   * Test that file_save_data() fails overwriting an existing file.
+   */
+  function testExistingError() {
+    $contents = $this->randomName(8);
+    $existing = $this->createFile(NULL, $contents);
+
+    // Check the overwrite error.
+    $result = file_save_data('asdf', $existing->uri, FILE_EXISTS_ERROR);
+    $this->assertFalse($result, t('Overwriting a file fails when FILE_EXISTS_ERROR is specified.'));
+    $this->assertEqual($contents, file_get_contents($existing->uri), t('Contents of existing file were unchanged.'));
+
+    // Check that no hooks were called while failing.
+    $this->assertFileHooksCalled(array());
+
+    // Ensure that the existing file wasn't overwritten.
+    $this->assertFileUnchanged($existing, file_load($existing->fid, TRUE));
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/SaveTest.php b/core/modules/file/lib/Drupal/file/Tests/SaveTest.php
new file mode 100644
index 0000000..e2611e5
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/SaveTest.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\SaveTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ * Tests saving files.
+ */
+class SaveTest extends FileManagedTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'File saving',
+      'description' => 'File saving tests',
+      'group' => 'File API',
+    );
+  }
+
+  function testFileSave() {
+    // Create a new file entity.
+    $file = entity_create('file', array(
+      'uid' => 1,
+      'filename' => 'druplicon.txt',
+      'uri' => 'public://druplicon.txt',
+      'filemime' => 'text/plain',
+      'timestamp' => 1,
+      'status' => FILE_STATUS_PERMANENT,
+    ));
+    file_put_contents($file->uri, 'hello world');
+
+    // Save it, inserting a new record.
+    $file->save();
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('insert'));
+
+    $this->assertTrue($file->fid > 0, t("A new file ID is set when saving a new file to the database."), 'File');
+    $loaded_file = db_query('SELECT * FROM {file_managed} f WHERE f.fid = :fid', array(':fid' => $file->fid))->fetchObject();
+    $this->assertNotNull($loaded_file, t("Record exists in the database."));
+    $this->assertEqual($loaded_file->status, $file->status, t("Status was saved correctly."));
+    $this->assertEqual($file->filesize, filesize($file->uri), t("File size was set correctly."), 'File');
+    $this->assertTrue($file->timestamp > 1, t("File size was set correctly."), 'File');
+    $this->assertEqual($loaded_file->langcode, LANGUAGE_NOT_SPECIFIED, t("Langcode was defaulted correctly."));
+
+    // Resave the file, updating the existing record.
+    file_test_reset();
+    $file->status = 7;
+    $file->langcode = 'en';
+    $file->save();
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('load', 'update'));
+
+    $this->assertEqual($file->fid, $file->fid, t("The file ID of an existing file is not changed when updating the database."), 'File');
+    $this->assertTrue($file->timestamp >= $file->timestamp, t("Timestamp didn't go backwards."), 'File');
+    $loaded_file = db_query('SELECT * FROM {file_managed} f WHERE f.fid = :fid', array(':fid' => $file->fid))->fetchObject();
+    $this->assertNotNull($loaded_file, t("Record still exists in the database."), 'File');
+    $this->assertEqual($loaded_file->status, $file->status, t("Status was saved correctly."));
+    $this->assertEqual($loaded_file->langcode, 'en', t("Langcode was saved correctly."));
+
+    // Try to insert a second file with the same name apart from case insensitivity
+    // to ensure the 'uri' index allows for filenames with different cases.
+    $file = entity_create('file', array(
+      'uid' => 1,
+      'filename' => 'DRUPLICON.txt',
+      'uri' => 'public://DRUPLICON.txt',
+      'filemime' => 'text/plain',
+      'timestamp' => 1,
+      'status' => FILE_STATUS_PERMANENT,
+    ));
+    file_put_contents($file->uri, 'hello world');
+    $file->save();
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/SaveUploadTest.php b/core/modules/file/lib/Drupal/file/Tests/SaveUploadTest.php
new file mode 100644
index 0000000..c0befba
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/SaveUploadTest.php
@@ -0,0 +1,328 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\SaveUploadTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ * Test the file_save_upload() function.
+ */
+class SaveUploadTest extends FileManagedTestBase {
+  /**
+   * An image file path for uploading.
+   */
+  protected $image;
+
+  /**
+   * A PHP file path for upload security testing.
+   */
+  protected $phpfile;
+
+  /**
+   * The largest file id when the test starts.
+   */
+  protected $maxFidBefore;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'File uploading',
+      'description' => 'Tests the file uploading functions.',
+      'group' => 'File API',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    $account = $this->drupalCreateUser(array('access content'));
+    $this->drupalLogin($account);
+
+    $image_files = $this->drupalGetTestFiles('image');
+    $this->image = entity_create('file', (array) current($image_files));
+
+    list(, $this->image_extension) = explode('.', $this->image->filename);
+    $this->assertTrue(is_file($this->image->uri), t("The image file we're going to upload exists."));
+
+    $this->phpfile = current($this->drupalGetTestFiles('php'));
+    $this->assertTrue(is_file($this->phpfile->uri), t("The PHP file we're going to upload exists."));
+
+    $this->maxFidBefore = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
+
+    // Upload with replace to guarantee there's something there.
+    $edit = array(
+      'file_test_replace' => FILE_EXISTS_REPLACE,
+      'files[file_test_upload]' => drupal_realpath($this->image->uri),
+    );
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
+
+    // Check that the correct hooks were called then clean out the hook
+    // counters.
+    $this->assertFileHooksCalled(array('validate', 'insert'));
+    file_test_reset();
+  }
+
+  /**
+   * Test the file_save_upload() function.
+   */
+  function testNormal() {
+    $max_fid_after = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
+    $this->assertTrue($max_fid_after > $this->maxFidBefore, t('A new file was created.'));
+    $file1 = file_load($max_fid_after);
+    $this->assertTrue($file1, t('Loaded the file.'));
+    // MIME type of the uploaded image may be either image/jpeg or image/png.
+    $this->assertEqual(substr($file1->filemime, 0, 5), 'image', 'A MIME type was set.');
+
+    // Reset the hook counters to get rid of the 'load' we just called.
+    file_test_reset();
+
+    // Upload a second file.
+    $max_fid_before = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
+    $image2 = current($this->drupalGetTestFiles('image'));
+    $edit = array('files[file_test_upload]' => drupal_realpath($image2->uri));
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertRaw(t('You WIN!'));
+    $max_fid_after = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('validate', 'insert'));
+
+    $file2 = file_load($max_fid_after);
+    $this->assertTrue($file2);
+    // MIME type of the uploaded image may be either image/jpeg or image/png.
+    $this->assertEqual(substr($file2->filemime, 0, 5), 'image', 'A MIME type was set.');
+
+    // Load both files using file_load_multiple().
+    $files = file_load_multiple(array($file1->fid, $file2->fid));
+    $this->assertTrue(isset($files[$file1->fid]), t('File was loaded successfully'));
+    $this->assertTrue(isset($files[$file2->fid]), t('File was loaded successfully'));
+
+    // Upload a third file to a subdirectory.
+    $image3 = current($this->drupalGetTestFiles('image'));
+    $image3_realpath = drupal_realpath($image3->uri);
+    $dir = $this->randomName();
+    $edit = array(
+      'files[file_test_upload]' => $image3_realpath,
+      'file_subdir' => $dir,
+    );
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertRaw(t('You WIN!'));
+    $this->assertTrue(is_file('temporary://' . $dir . '/' . trim(drupal_basename($image3_realpath))));
+
+    // Check that file_load_multiple() with no arguments returns FALSE.
+    $this->assertFalse(file_load_multiple(), t('No files were loaded.'));
+  }
+
+  /**
+   * Test extension handling.
+   */
+  function testHandleExtension() {
+    // The file being tested is a .gif which is in the default safe list
+    // of extensions to allow when the extension validator isn't used. This is
+    // implicitly tested at the testNormal() test. Here we tell
+    // file_save_upload() to only allow ".foo".
+    $extensions = 'foo';
+    $edit = array(
+      'file_test_replace' => FILE_EXISTS_REPLACE,
+      'files[file_test_upload]' => drupal_realpath($this->image->uri),
+      'extensions' => $extensions,
+    );
+
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $message = t('Only files with the following extensions are allowed:') . ' <em class="placeholder">' . $extensions . '</em>';
+    $this->assertRaw($message, t('Can\'t upload a disallowed extension'));
+    $this->assertRaw(t('Epic upload FAIL!'), t('Found the failure message.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('validate'));
+
+    // Reset the hook counters.
+    file_test_reset();
+
+    $extensions = 'foo ' . $this->image_extension;
+    // Now tell file_save_upload() to allow the extension of our test image.
+    $edit = array(
+      'file_test_replace' => FILE_EXISTS_REPLACE,
+      'files[file_test_upload]' => drupal_realpath($this->image->uri),
+      'extensions' => $extensions,
+    );
+
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertNoRaw(t('Only files with the following extensions are allowed:'), t('Can upload an allowed extension.'));
+    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('validate', 'load', 'update'));
+
+    // Reset the hook counters.
+    file_test_reset();
+
+    // Now tell file_save_upload() to allow any extension.
+    $edit = array(
+      'file_test_replace' => FILE_EXISTS_REPLACE,
+      'files[file_test_upload]' => drupal_realpath($this->image->uri),
+      'allow_all_extensions' => TRUE,
+    );
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertNoRaw(t('Only files with the following extensions are allowed:'), t('Can upload any extension.'));
+    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('validate', 'load', 'update'));
+  }
+
+  /**
+   * Test dangerous file handling.
+   */
+  function testHandleDangerousFile() {
+    // Allow the .php extension and make sure it gets renamed to .txt for
+    // safety. Also check to make sure its MIME type was changed.
+    $edit = array(
+      'file_test_replace' => FILE_EXISTS_REPLACE,
+      'files[file_test_upload]' => drupal_realpath($this->phpfile->uri),
+      'is_image_file' => FALSE,
+      'extensions' => 'php',
+    );
+
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $message = t('For security reasons, your upload has been renamed to') . ' <em class="placeholder">' . $this->phpfile->filename . '.txt' . '</em>';
+    $this->assertRaw($message, t('Dangerous file was renamed.'));
+    $this->assertRaw(t('File MIME type is text/plain.'), t('Dangerous file\'s MIME type was changed.'));
+    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('validate', 'insert'));
+
+    // Ensure dangerous files are not renamed when insecure uploads is TRUE.
+    // Turn on insecure uploads.
+    variable_set('allow_insecure_uploads', 1);
+    // Reset the hook counters.
+    file_test_reset();
+
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertNoRaw(t('For security reasons, your upload has been renamed'), t('Found no security message.'));
+    $this->assertRaw(t('File name is !filename', array('!filename' => $this->phpfile->filename)), t('Dangerous file was not renamed when insecure uploads is TRUE.'));
+    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('validate', 'insert'));
+
+    // Turn off insecure uploads.
+    variable_set('allow_insecure_uploads', 0);
+  }
+
+  /**
+   * Test file munge handling.
+   */
+  function testHandleFileMunge() {
+    // Ensure insecure uploads are disabled for this test.
+    variable_set('allow_insecure_uploads', 0);
+    $this->image = file_move($this->image, $this->image->uri . '.foo.' . $this->image_extension);
+
+    // Reset the hook counters to get rid of the 'move' we just called.
+    file_test_reset();
+
+    $extensions = $this->image_extension;
+    $edit = array(
+      'files[file_test_upload]' => drupal_realpath($this->image->uri),
+      'extensions' => $extensions,
+    );
+
+    $munged_filename = $this->image->filename;
+    $munged_filename = substr($munged_filename, 0, strrpos($munged_filename, '.'));
+    $munged_filename .= '_.' . $this->image_extension;
+
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertRaw(t('For security reasons, your upload has been renamed'), t('Found security message.'));
+    $this->assertRaw(t('File name is !filename', array('!filename' => $munged_filename)), t('File was successfully munged.'));
+    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('validate', 'insert'));
+
+    // Ensure we don't munge files if we're allowing any extension.
+    // Reset the hook counters.
+    file_test_reset();
+
+    $edit = array(
+      'files[file_test_upload]' => drupal_realpath($this->image->uri),
+      'allow_all_extensions' => TRUE,
+    );
+
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertNoRaw(t('For security reasons, your upload has been renamed'), t('Found no security message.'));
+    $this->assertRaw(t('File name is !filename', array('!filename' => $this->image->filename)), t('File was not munged when allowing any extension.'));
+    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('validate', 'insert'));
+  }
+
+  /**
+   * Test renaming when uploading over a file that already exists.
+   */
+  function testExistingRename() {
+    $edit = array(
+      'file_test_replace' => FILE_EXISTS_RENAME,
+      'files[file_test_upload]' => drupal_realpath($this->image->uri)
+    );
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('validate', 'insert'));
+  }
+
+  /**
+   * Test replacement when uploading over a file that already exists.
+   */
+  function testExistingReplace() {
+    $edit = array(
+      'file_test_replace' => FILE_EXISTS_REPLACE,
+      'files[file_test_upload]' => drupal_realpath($this->image->uri)
+    );
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
+
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('validate', 'load', 'update'));
+  }
+
+  /**
+   * Test for failure when uploading over a file that already exists.
+   */
+  function testExistingError() {
+    $edit = array(
+      'file_test_replace' => FILE_EXISTS_ERROR,
+      'files[file_test_upload]' => drupal_realpath($this->image->uri)
+    );
+    $this->drupalPost('file-test/upload', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertRaw(t('Epic upload FAIL!'), t('Found the failure message.'));
+
+    // Check that the no hooks were called while failing.
+    $this->assertFileHooksCalled(array());
+  }
+
+  /**
+   * Test for no failures when not uploading a file.
+   */
+  function testNoUpload() {
+    $this->drupalPost('file-test/upload', array(), t('Submit'));
+    $this->assertNoRaw(t('Epic upload FAIL!'), t('Failure message not found.'));
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/SpaceUsedTest.php b/core/modules/file/lib/Drupal/file/Tests/SpaceUsedTest.php
new file mode 100644
index 0000000..db62d5a
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/SpaceUsedTest.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\SpaceUsedTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ *  This will run tests against the file_space_used() function.
+ */
+class SpaceUsedTest extends FileManagedTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'File space used tests',
+      'description' => 'Tests the file_space_used() function.',
+      'group' => 'File API',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    // Create records for a couple of users with different sizes.
+    $file = array('uid' => 2, 'uri' => 'public://example1.txt', 'filesize' => 50, 'status' => FILE_STATUS_PERMANENT);
+    drupal_write_record('file_managed', $file);
+    $file = array('uid' => 2, 'uri' => 'public://example2.txt', 'filesize' => 20, 'status' => FILE_STATUS_PERMANENT);
+    drupal_write_record('file_managed', $file);
+    $file = array('uid' => 3, 'uri' => 'public://example3.txt', 'filesize' => 100, 'status' => FILE_STATUS_PERMANENT);
+    drupal_write_record('file_managed', $file);
+    $file = array('uid' => 3, 'uri' => 'public://example4.txt', 'filesize' => 200, 'status' => FILE_STATUS_PERMANENT);
+    drupal_write_record('file_managed', $file);
+
+    // Now create some non-permanent files.
+    $file = array('uid' => 2, 'uri' => 'public://example5.txt', 'filesize' => 1, 'status' => 0);
+    drupal_write_record('file_managed', $file);
+    $file = array('uid' => 3, 'uri' => 'public://example6.txt', 'filesize' => 3, 'status' => 0);
+    drupal_write_record('file_managed', $file);
+  }
+
+  /**
+   * Test different users with the default status.
+   */
+  function testFileSpaceUsed() {
+    // Test different users with default status.
+    $this->assertEqual(file_space_used(2), 70);
+    $this->assertEqual(file_space_used(3), 300);
+    $this->assertEqual(file_space_used(), 370);
+
+    // Test the status fields
+    $this->assertEqual(file_space_used(NULL, 0), 4);
+    $this->assertEqual(file_space_used(NULL, FILE_STATUS_PERMANENT), 370);
+
+    // Test both the user and status.
+    $this->assertEqual(file_space_used(1, 0), 0);
+    $this->assertEqual(file_space_used(1, FILE_STATUS_PERMANENT), 0);
+    $this->assertEqual(file_space_used(2, 0), 1);
+    $this->assertEqual(file_space_used(2, FILE_STATUS_PERMANENT), 70);
+    $this->assertEqual(file_space_used(3, 0), 3);
+    $this->assertEqual(file_space_used(3, FILE_STATUS_PERMANENT), 300);
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/UsageTest.php b/core/modules/file/lib/Drupal/file/Tests/UsageTest.php
new file mode 100644
index 0000000..aa4e182
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/UsageTest.php
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\UsageTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ * Tests file usage functions.
+ */
+class UsageTest extends FileManagedTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'File usage',
+      'description' => 'Tests the file usage functions.',
+      'group' => 'File API',
+    );
+  }
+
+  /**
+   * Tests file_usage_list().
+   */
+  function testGetUsage() {
+    $file = $this->createFile();
+    db_insert('file_usage')
+      ->fields(array(
+        'fid' => $file->fid,
+        'module' => 'testing',
+        'type' => 'foo',
+        'id' => 1,
+        'count' => 1
+      ))
+      ->execute();
+    db_insert('file_usage')
+      ->fields(array(
+        'fid' => $file->fid,
+        'module' => 'testing',
+        'type' => 'bar',
+        'id' => 2,
+        'count' => 2
+      ))
+      ->execute();
+
+    $usage = file_usage_list($file);
+
+    $this->assertEqual(count($usage['testing']), 2, t('Returned the correct number of items.'));
+    $this->assertTrue(isset($usage['testing']['foo'][1]), t('Returned the correct id.'));
+    $this->assertTrue(isset($usage['testing']['bar'][2]), t('Returned the correct id.'));
+    $this->assertEqual($usage['testing']['foo'][1], 1, t('Returned the correct count.'));
+    $this->assertEqual($usage['testing']['bar'][2], 2, t('Returned the correct count.'));
+  }
+
+  /**
+   * Tests file_usage_add().
+   */
+  function testAddUsage() {
+    $file = $this->createFile();
+    file_usage_add($file, 'testing', 'foo', 1);
+    // Add the file twice to ensure that the count is incremented rather than
+    // creating additional records.
+    file_usage_add($file, 'testing', 'bar', 2);
+    file_usage_add($file, 'testing', 'bar', 2);
+
+    $usage = db_select('file_usage', 'f')
+      ->fields('f')
+      ->condition('f.fid', $file->fid)
+      ->execute()
+      ->fetchAllAssoc('id');
+    $this->assertEqual(count($usage), 2, t('Created two records'));
+    $this->assertEqual($usage[1]->module, 'testing', t('Correct module'));
+    $this->assertEqual($usage[2]->module, 'testing', t('Correct module'));
+    $this->assertEqual($usage[1]->type, 'foo', t('Correct type'));
+    $this->assertEqual($usage[2]->type, 'bar', t('Correct type'));
+    $this->assertEqual($usage[1]->count, 1, t('Correct count'));
+    $this->assertEqual($usage[2]->count, 2, t('Correct count'));
+  }
+
+  /**
+   * Tests file_usage_delete().
+   */
+  function testRemoveUsage() {
+    $file = $this->createFile();
+    db_insert('file_usage')
+      ->fields(array(
+        'fid' => $file->fid,
+        'module' => 'testing',
+        'type' => 'bar',
+        'id' => 2,
+        'count' => 3,
+      ))
+      ->execute();
+
+    // Normal decrement.
+    file_usage_delete($file, 'testing', 'bar', 2);
+    $count = db_select('file_usage', 'f')
+      ->fields('f', array('count'))
+      ->condition('f.fid', $file->fid)
+      ->execute()
+      ->fetchField();
+    $this->assertEqual(2, $count, t('The count was decremented correctly.'));
+
+    // Multiple decrement and removal.
+    file_usage_delete($file, 'testing', 'bar', 2, 2);
+    $count = db_select('file_usage', 'f')
+      ->fields('f', array('count'))
+      ->condition('f.fid', $file->fid)
+      ->execute()
+      ->fetchField();
+    $this->assertIdentical(FALSE, $count, t('The count was removed entirely when empty.'));
+
+    // Non-existent decrement.
+    file_usage_delete($file, 'testing', 'bar', 2);
+    $count = db_select('file_usage', 'f')
+      ->fields('f', array('count'))
+      ->condition('f.fid', $file->fid)
+      ->execute()
+      ->fetchField();
+    $this->assertIdentical(FALSE, $count, t('Decrementing non-exist record complete.'));
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/ValidateTest.php b/core/modules/file/lib/Drupal/file/Tests/ValidateTest.php
new file mode 100644
index 0000000..2418382
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/ValidateTest.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\ValidateTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ * Tests the file_validate() function.
+ */
+class ValidateTest extends FileManagedTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'File validate',
+      'description' => 'Tests the file_validate() function.',
+      'group' => 'File API',
+    );
+  }
+
+  /**
+   * Test that the validators passed into are checked.
+   */
+  function testCallerValidation() {
+    $file = $this->createFile();
+
+    // Empty validators.
+    $this->assertEqual(file_validate($file, array()), array(), t('Validating an empty array works successfully.'));
+    $this->assertFileHooksCalled(array('validate'));
+
+    // Use the file_test.module's test validator to ensure that passing tests
+    // return correctly.
+    file_test_reset();
+    file_test_set_return('validate', array());
+    $passing = array('file_test_validator' => array(array()));
+    $this->assertEqual(file_validate($file, $passing), array(), t('Validating passes.'));
+    $this->assertFileHooksCalled(array('validate'));
+
+    // Now test for failures in validators passed in and by hook_validate.
+    file_test_reset();
+    file_test_set_return('validate', array('Epic fail'));
+    $failing = array('file_test_validator' => array(array('Failed', 'Badly')));
+    $this->assertEqual(file_validate($file, $failing), array('Failed', 'Badly', 'Epic fail'), t('Validating returns errors.'));
+    $this->assertFileHooksCalled(array('validate'));
+  }
+}
diff --git a/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php b/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php
new file mode 100644
index 0000000..67b72b7
--- /dev/null
+++ b/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php
@@ -0,0 +1,160 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file\Tests\ValidatorTest.
+ */
+
+namespace Drupal\file\Tests;
+
+/**
+ *  This will run tests against the file validation functions (file_validate_*).
+ */
+class ValidatorTest extends FileManagedTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'File validator tests',
+      'description' => 'Tests the functions used to validate uploaded files.',
+      'group' => 'File API',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    $this->image = entity_create('file', array());
+    $this->image->uri = 'core/misc/druplicon.png';
+    $this->image->filename = drupal_basename($this->image->uri);
+
+    $this->non_image = entity_create('file', array());
+    $this->non_image->uri = 'core/misc/jquery.js';
+    $this->non_image->filename = drupal_basename($this->non_image->uri);
+  }
+
+  /**
+   * Test the file_validate_extensions() function.
+   */
+  function testFileValidateExtensions() {
+    $file = entity_create('file', array('filename' => 'asdf.txt'));
+    $errors = file_validate_extensions($file, 'asdf txt pork');
+    $this->assertEqual(count($errors), 0, t('Valid extension accepted.'), 'File');
+
+    $file->filename = 'asdf.txt';
+    $errors = file_validate_extensions($file, 'exe png');
+    $this->assertEqual(count($errors), 1, t('Invalid extension blocked.'), 'File');
+  }
+
+  /**
+   *  This ensures a specific file is actually an image.
+   */
+  function testFileValidateIsImage() {
+    $this->assertTrue(file_exists($this->image->uri), t('The image being tested exists.'), 'File');
+    $errors = file_validate_is_image($this->image);
+    $this->assertEqual(count($errors), 0, t('No error reported for our image file.'), 'File');
+
+    $this->assertTrue(file_exists($this->non_image->uri), t('The non-image being tested exists.'), 'File');
+    $errors = file_validate_is_image($this->non_image);
+    $this->assertEqual(count($errors), 1, t('An error reported for our non-image file.'), 'File');
+  }
+
+  /**
+   *  This ensures the resolution of a specific file is within bounds.
+   *  The image will be resized if it's too large.
+   */
+  function testFileValidateImageResolution() {
+    // Non-images.
+    $errors = file_validate_image_resolution($this->non_image);
+    $this->assertEqual(count($errors), 0, t("Shouldn't get any errors for a non-image file."), 'File');
+    $errors = file_validate_image_resolution($this->non_image, '50x50', '100x100');
+    $this->assertEqual(count($errors), 0, t("Don't check the resolution on non files."), 'File');
+
+    // Minimum size.
+    $errors = file_validate_image_resolution($this->image);
+    $this->assertEqual(count($errors), 0, t('No errors for an image when there is no minimum or maximum resolution.'), 'File');
+    $errors = file_validate_image_resolution($this->image, 0, '200x1');
+    $this->assertEqual(count($errors), 1, t("Got an error for an image that wasn't wide enough."), 'File');
+    $errors = file_validate_image_resolution($this->image, 0, '1x200');
+    $this->assertEqual(count($errors), 1, t("Got an error for an image that wasn't tall enough."), 'File');
+    $errors = file_validate_image_resolution($this->image, 0, '200x200');
+    $this->assertEqual(count($errors), 1, t('Small images report an error.'), 'File');
+
+    // Maximum size.
+    if (image_get_toolkit()) {
+      // Copy the image so that the original doesn't get resized.
+      copy('core/misc/druplicon.png', 'temporary://druplicon.png');
+      $this->image->uri = 'temporary://druplicon.png';
+
+      $errors = file_validate_image_resolution($this->image, '10x5');
+      $this->assertEqual(count($errors), 0, t('No errors should be reported when an oversized image can be scaled down.'), 'File');
+
+      $info = image_get_info($this->image->uri);
+      $this->assertTrue($info['width'] <= 10, t('Image scaled to correct width.'), 'File');
+      $this->assertTrue($info['height'] <= 5, t('Image scaled to correct height.'), 'File');
+
+      drupal_unlink('temporary://druplicon.png');
+    }
+    else {
+      // TODO: should check that the error is returned if no toolkit is available.
+      $errors = file_validate_image_resolution($this->image, '5x10');
+      $this->assertEqual(count($errors), 1, t("Oversize images that can't be scaled get an error."), 'File');
+    }
+  }
+
+  /**
+   *  This will ensure the filename length is valid.
+   */
+  function testFileValidateNameLength() {
+    // Create a new file entity.
+    $file = entity_create('file', array());
+
+    // Add a filename with an allowed length and test it.
+    $file->filename = str_repeat('x', 240);
+    $this->assertEqual(strlen($file->filename), 240);
+    $errors = file_validate_name_length($file);
+    $this->assertEqual(count($errors), 0, t('No errors reported for 240 length filename.'), 'File');
+
+    // Add a filename with a length too long and test it.
+    $file->filename = str_repeat('x', 241);
+    $errors = file_validate_name_length($file);
+    $this->assertEqual(count($errors), 1, t('An error reported for 241 length filename.'), 'File');
+
+    // Add a filename with an empty string and test it.
+    $file->filename = '';
+    $errors = file_validate_name_length($file);
+    $this->assertEqual(count($errors), 1, t('An error reported for 0 length filename.'), 'File');
+  }
+
+
+  /**
+   * Test file_validate_size().
+   */
+  function testFileValidateSize() {
+    global $user;
+    $original_user = $user;
+    drupal_save_session(FALSE);
+
+    // Run these test as uid = 1.
+    $user = user_load(1);
+
+    $file = entity_create('file', array('filesize' => 999999));
+    $errors = file_validate_size($file, 1, 1);
+    $this->assertEqual(count($errors), 0, t('No size limits enforced on uid=1.'), 'File');
+
+    // Run these tests as a regular user.
+    $user = $this->drupalCreateUser();
+
+    // Create a file with a size of 1000 bytes, and quotas of only 1 byte.
+    $file = entity_create('file', array('filesize' => 1000));
+    $errors = file_validate_size($file, 0, 0);
+    $this->assertEqual(count($errors), 0, t('No limits means no errors.'), 'File');
+    $errors = file_validate_size($file, 1, 0);
+    $this->assertEqual(count($errors), 1, t('Error for the file being over the limit.'), 'File');
+    $errors = file_validate_size($file, 0, 1);
+    $this->assertEqual(count($errors), 1, t('Error for the user being over their limit.'), 'File');
+    $errors = file_validate_size($file, 1, 1);
+    $this->assertEqual(count($errors), 2, t('Errors for both the file and their limit.'), 'File');
+
+    $user = $original_user;
+    drupal_save_session(TRUE);
+  }
+}
diff --git a/core/modules/system/tests/modules/file_test/file_test.info b/core/modules/file/tests/file_test/file_test.info
similarity index 100%
rename from core/modules/system/tests/modules/file_test/file_test.info
rename to core/modules/file/tests/file_test/file_test.info
diff --git a/core/modules/system/tests/modules/file_test/file_test.module b/core/modules/file/tests/file_test/file_test.module
similarity index 91%
rename from core/modules/system/tests/modules/file_test/file_test.module
rename to core/modules/file/tests/file_test/file_test.module
index a31c1d0..46b8604 100644
--- a/core/modules/system/tests/modules/file_test/file_test.module
+++ b/core/modules/file/tests/file_test/file_test.module
@@ -8,14 +8,11 @@
  * calling file_test_get_calls() or file_test_set_return().
  */
 
-use Drupal\Core\StreamWrapper\LocalStream;
-use Drupal\Core\StreamWrapper\PublicStream;
-use Drupal\Core\File\File;
+use Drupal\file\File;
 
 const FILE_URL_TEST_CDN_1 = 'http://cdn1.example.com';
 const FILE_URL_TEST_CDN_2 = 'http://cdn2.example.com';
 
-
 /**
  * Implements hook_menu().
  */
@@ -37,12 +34,12 @@ function file_test_stream_wrappers() {
   return array(
     'dummy' => array(
       'name' => t('Dummy files'),
-      'class' => 'DrupalDummyStreamWrapper',
+      'class' => 'Drupal\file_test\DummyStreamWrapper',
       'description' => t('Dummy wrapper for simpletest.'),
     ),
     'dummy-remote' => array(
       'name' => t('Dummy files (remote)'),
-      'class' => 'DrupalDummyRemoteStreamWrapper',
+      'class' => 'Drupal\file_test\DummyRemoteStreamWrapper',
       'description' => t('Dummy wrapper for simpletest (remote).'),
     ),
   );
@@ -422,43 +419,37 @@ function file_test_file_mimetype_mapping_alter(&$mapping) {
 }
 
 /**
- * Helper class for testing the stream wrapper registry.
- *
- * Dummy stream wrapper implementation (dummy://).
+ * Helper validator that returns the $errors parameter.
  */
-class DrupalDummyStreamWrapper extends LocalStream {
-  function getDirectoryPath() {
-    return variable_get('stream_public_path', 'sites/default/files');
-  }
-
-  /**
-   * Override getInternalUri().
-   *
-   * Return a dummy path for testing.
-   */
-  function getInternalUri() {
-    return '/dummy/example.txt';
-  }
-
-  /**
-   * Override getExternalUrl().
-   *
-   * Return the HTML URI of a public file.
-   */
-  function getExternalUrl() {
-    return '/dummy/example.txt';
-  }
+function file_test_validator(File $file, $errors) {
+  return $errors;
 }
 
 /**
- * Helper class for testing the stream wrapper registry.
+ * Helper function for testing file_scan_directory().
  *
- * Dummy remote stream wrapper implementation (dummy-remote://).
+ * Each time the function is called the file is stored in a static variable.
+ * When the function is called with no $filepath parameter, the results are
+ * returned.
  *
- * Basically just the public scheme but not returning a local file for realpath.
+ * @param $filepath
+ *   File path
+ * @return
+ *   If $filepath is NULL, an array of all previous $filepath parameters
  */
-class DrupalDummyRemoteStreamWrapper extends PublicStream {
-  function realpath() {
-    return FALSE;
+function file_test_file_scan_callback($filepath = NULL) {
+  $files = &drupal_static(__FUNCTION__, array());
+  if (isset($filepath)) {
+    $files[] = $filepath;
+  }
+  else {
+    return $files;
   }
 }
+
+/**
+ * Reset static variables used by file_test_file_scan_callback().
+ */
+function file_test_file_scan_callback_reset() {
+  drupal_static_reset('file_test_file_scan_callback');
+}
diff --git a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyRemoteStreamWrapper.php b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyRemoteStreamWrapper.php
new file mode 100644
index 0000000..2741196
--- /dev/null
+++ b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyRemoteStreamWrapper.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file_test\DummyRemoteStreamWrapper.
+ */
+
+namespace Drupal\file_test;
+
+use Drupal\Core\StreamWrapper\PublicStream;
+
+/**
+ * Helper class for testing the stream wrapper registry.
+ *
+ * Dummy remote stream wrapper implementation (dummy-remote://).
+ *
+ * Basically just the public scheme but not returning a local file for realpath.
+ */
+class DummyRemoteStreamWrapper extends PublicStream {
+  function realpath() {
+    return FALSE;
+  }
+}
diff --git a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyStreamWrapper.php b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyStreamWrapper.php
new file mode 100644
index 0000000..0651f37
--- /dev/null
+++ b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyStreamWrapper.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\file_test\DummyStreamWrapper.
+ */
+
+namespace Drupal\file_test;
+
+use Drupal\Core\StreamWrapper\LocalStream;
+
+/**
+ * Helper class for testing the stream wrapper registry.
+ *
+ * Dummy stream wrapper implementation (dummy://).
+ */
+class DummyStreamWrapper extends LocalStream {
+  function getDirectoryPath() {
+    return variable_get('stream_public_path', 'sites/default/files');
+  }
+
+  /**
+   * Override getInternalUri().
+   *
+   * Return a dummy path for testing.
+   */
+  function getInternalUri() {
+    return '/dummy/example.txt';
+  }
+
+  /**
+   * Override getExternalUrl().
+   *
+   * Return the HTML URI of a public file.
+   */
+  function getExternalUrl() {
+    return '/dummy/example.txt';
+  }
+}
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index f3bf83d..9cd7763 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -8,7 +8,7 @@
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpFoundation\StreamedResponse;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
-use Drupal\Core\File\File;
+use Drupal\file\File;
 
 /**
  * Image style constant for user presets in the database.
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php b/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php
new file mode 100644
index 0000000..5d57bdf
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php
@@ -0,0 +1,131 @@
+<?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."));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/FileTestBase.php b/core/modules/system/lib/Drupal/system/Tests/File/FileTestBase.php
new file mode 100644
index 0000000..f301401
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/FileTestBase.php
@@ -0,0 +1,198 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\FileTestBase.
+ */
+
+namespace Drupal\system\Tests\File;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Base class for file tests that adds some additional file specific
+ * assertions and helper functions.
+ */
+class FileTestBase extends WebTestBase {
+
+  function setUp() {
+    $modules = func_get_args();
+    $modules = (isset($modules[0]) && is_array($modules[0]) ? $modules[0] : $modules);
+    parent::setUp($modules);
+
+    // Make sure that custom stream wrappers are registered.
+    // @todo This has the potential to be a major bug deeply buried in File API;
+    //   file_unmanaged_*() API functions and test functions are invoking native
+    //   PHP functions directly, whereas Drupal's custom stream wrappers are not
+    //   registered yet.
+    file_get_stream_wrappers();
+  }
+
+  /**
+   * Check that two files have the same values for all fields other than the
+   * timestamp.
+   *
+   * @param $before
+   *   File object to compare.
+   * @param $after
+   *   File object to compare.
+   */
+  function assertFileUnchanged($before, $after) {
+    $this->assertEqual($before->fid, $after->fid, t('File id is the same: %file1 == %file2.', array('%file1' => $before->fid, '%file2' => $after->fid)), 'File unchanged');
+    $this->assertEqual($before->uid, $after->uid, t('File owner is the same: %file1 == %file2.', array('%file1' => $before->uid, '%file2' => $after->uid)), 'File unchanged');
+    $this->assertEqual($before->filename, $after->filename, t('File name is the same: %file1 == %file2.', array('%file1' => $before->filename, '%file2' => $after->filename)), 'File unchanged');
+    $this->assertEqual($before->uri, $after->uri, t('File path is the same: %file1 == %file2.', array('%file1' => $before->uri, '%file2' => $after->uri)), 'File unchanged');
+    $this->assertEqual($before->filemime, $after->filemime, t('File MIME type is the same: %file1 == %file2.', array('%file1' => $before->filemime, '%file2' => $after->filemime)), 'File unchanged');
+    $this->assertEqual($before->filesize, $after->filesize, t('File size is the same: %file1 == %file2.', array('%file1' => $before->filesize, '%file2' => $after->filesize)), 'File unchanged');
+    $this->assertEqual($before->status, $after->status, t('File status is the same: %file1 == %file2.', array('%file1' => $before->status, '%file2' => $after->status)), 'File unchanged');
+  }
+
+  /**
+   * Check that two files are not the same by comparing the fid and filepath.
+   *
+   * @param $file1
+   *   File object to compare.
+   * @param $file2
+   *   File object to compare.
+   */
+  function assertDifferentFile($file1, $file2) {
+    $this->assertNotEqual($file1->fid, $file2->fid, t('Files have different ids: %file1 != %file2.', array('%file1' => $file1->fid, '%file2' => $file2->fid)), 'Different file');
+    $this->assertNotEqual($file1->uri, $file2->uri, t('Files have different paths: %file1 != %file2.', array('%file1' => $file1->uri, '%file2' => $file2->uri)), 'Different file');
+  }
+
+  /**
+   * Check that two files are the same by comparing the fid and filepath.
+   *
+   * @param $file1
+   *   File object to compare.
+   * @param $file2
+   *   File object to compare.
+   */
+  function assertSameFile($file1, $file2) {
+    $this->assertEqual($file1->fid, $file2->fid, t('Files have the same ids: %file1 == %file2.', array('%file1' => $file1->fid, '%file2-fid' => $file2->fid)), 'Same file');
+    $this->assertEqual($file1->uri, $file2->uri, t('Files have the same path: %file1 == %file2.', array('%file1' => $file1->uri, '%file2' => $file2->uri)), 'Same file');
+  }
+
+  /**
+   * Helper function to test the permissions of a file.
+   *
+   * @param $filepath
+   *   String file path.
+   * @param $expected_mode
+   *   Octal integer like 0664 or 0777.
+   * @param $message
+   *   Optional message.
+   */
+  function assertFilePermissions($filepath, $expected_mode, $message = NULL) {
+    // Clear out PHP's file stat cache to be sure we see the current value.
+    clearstatcache();
+
+    // Mask out all but the last three octets.
+    $actual_mode = fileperms($filepath) & 0777;
+
+    // PHP on Windows has limited support for file permissions. Usually each of
+    // "user", "group" and "other" use one octal digit (3 bits) to represent the
+    // read/write/execute bits. On Windows, chmod() ignores the "group" and
+    // "other" bits, and fileperms() returns the "user" bits in all three
+    // positions. $expected_mode is updated to reflect this.
+    if (substr(PHP_OS, 0, 3) == 'WIN') {
+      // Reset the "group" and "other" bits.
+      $expected_mode = $expected_mode & 0700;
+      // Shift the "user" bits to the "group" and "other" positions also.
+      $expected_mode = $expected_mode | $expected_mode >> 3 | $expected_mode >> 6;
+    }
+
+    if (!isset($message)) {
+      $message = t('Expected file permission to be %expected, actually were %actual.', array('%actual' => decoct($actual_mode), '%expected' => decoct($expected_mode)));
+    }
+    $this->assertEqual($actual_mode, $expected_mode, $message);
+  }
+
+  /**
+   * Helper function to test the permissions of a directory.
+   *
+   * @param $directory
+   *   String directory path.
+   * @param $expected_mode
+   *   Octal integer like 0664 or 0777.
+   * @param $message
+   *   Optional message.
+   */
+  function assertDirectoryPermissions($directory, $expected_mode, $message = NULL) {
+    // Clear out PHP's file stat cache to be sure we see the current value.
+    clearstatcache();
+
+    // Mask out all but the last three octets.
+    $actual_mode = fileperms($directory) & 0777;
+
+    // PHP on Windows has limited support for file permissions. Usually each of
+    // "user", "group" and "other" use one octal digit (3 bits) to represent the
+    // read/write/execute bits. On Windows, chmod() ignores the "group" and
+    // "other" bits, and fileperms() returns the "user" bits in all three
+    // positions. $expected_mode is updated to reflect this.
+    if (substr(PHP_OS, 0, 3) == 'WIN') {
+      // Reset the "group" and "other" bits.
+      $expected_mode = $expected_mode & 0700;
+      // Shift the "user" bits to the "group" and "other" positions also.
+      $expected_mode = $expected_mode | $expected_mode >> 3 | $expected_mode >> 6;
+    }
+
+    if (!isset($message)) {
+      $message = t('Expected directory permission to be %expected, actually were %actual.', array('%actual' => decoct($actual_mode), '%expected' => decoct($expected_mode)));
+    }
+    $this->assertEqual($actual_mode, $expected_mode, $message);
+  }
+
+  /**
+   * Create a directory and assert it exists.
+   *
+   * @param $path
+   *   Optional string with a directory path. If none is provided, a random
+   *   name in the site's files directory will be used.
+   * @return
+   *   The path to the directory.
+   */
+  function createDirectory($path = NULL) {
+    // A directory to operate on.
+    if (!isset($path)) {
+      $path = file_default_scheme() . '://' . $this->randomName();
+    }
+    $this->assertTrue(drupal_mkdir($path) && is_dir($path), t('Directory was created successfully.'));
+    return $path;
+  }
+
+    /**
+   * Create a file and return the URI of it.
+   *
+   * @param $filepath
+   *   Optional string specifying the file path. If none is provided then a
+   *   randomly named file will be created in the site's files directory.
+   * @param $contents
+   *   Optional contents to save into the file. If a NULL value is provided an
+   *   arbitrary string will be used.
+   * @param $scheme
+   *   Optional string indicating the stream scheme to use. Drupal core includes
+   *   public, private, and temporary. The public wrapper is the default.
+   * @return
+   *   File URI.
+   */
+  function createUri($filepath = NULL, $contents = NULL, $scheme = NULL) {
+    if (!isset($filepath)) {
+      // Prefix with non-latin characters to ensure that all file-related
+      // tests work with international filenames.
+      $filepath = 'Файл для тестирования ' . $this->randomName();
+    }
+    if (!isset($scheme)) {
+      $scheme = file_default_scheme();
+    }
+    $filepath = $scheme . '://' . $filepath;
+
+    if (!isset($contents)) {
+      $contents = "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data.";
+    }
+
+    file_put_contents($filepath, $contents);
+    $this->assertTrue(is_file($filepath), t('The test file exists on the disk.'), 'Create test file');
+    return $filepath;
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/MimeTypeTest.php b/core/modules/system/lib/Drupal/system/Tests/File/MimeTypeTest.php
new file mode 100644
index 0000000..cb90b85
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/MimeTypeTest.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\MimeTypeTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests for file_get_mimetype().
+ */
+class MimeTypeTest extends WebTestBase {
+  function setUp() {
+    parent::setUp('file_test');
+  }
+
+  public static function getInfo() {
+    return array(
+      'name' => 'File mimetypes',
+      'description' => 'Test filename mimetype detection.',
+      'group' => 'File API',
+    );
+  }
+
+  /**
+   * Test mapping of mimetypes from filenames.
+   */
+  public function testFileMimeTypeDetection() {
+    $prefix = 'public://';
+
+    $test_case = array(
+      'test.jar' => 'application/java-archive',
+      'test.jpeg' => 'image/jpeg',
+      'test.JPEG' => 'image/jpeg',
+      'test.jpg' => 'image/jpeg',
+      'test.jar.jpg' => 'image/jpeg',
+      'test.jpg.jar' => 'application/java-archive',
+      'test.pcf.Z' => 'application/x-font',
+      'pcf.z' => 'application/octet-stream',
+      'jar' => 'application/octet-stream',
+      'some.junk' => 'application/octet-stream',
+      'foo.file_test_1' => 'madeup/file_test_1',
+      'foo.file_test_2' => 'madeup/file_test_2',
+      'foo.doc' => 'madeup/doc',
+      'test.ogg' => 'audio/ogg',
+    );
+
+    // Test using default mappings.
+    foreach ($test_case as $input => $expected) {
+      // Test stream [URI].
+      $output = file_get_mimetype($prefix . $input);
+      $this->assertIdentical($output, $expected, t('Mimetype for %input is %output (expected: %expected).', array('%input' => $input, '%output' => $output, '%expected' => $expected)));
+
+      // Test normal path equivalent
+      $output = file_get_mimetype($input);
+      $this->assertIdentical($output, $expected, t('Mimetype (using default mappings) for %input is %output (expected: %expected).', array('%input' => $input, '%output' => $output, '%expected' => $expected)));
+    }
+
+    // Now test passing in the map.
+    $mapping = array(
+      'mimetypes' => array(
+        0 => 'application/java-archive',
+        1 => 'image/jpeg',
+      ),
+      'extensions' => array(
+         'jar' => 0,
+         'jpg' => 1,
+      )
+    );
+
+    $test_case = array(
+      'test.jar' => 'application/java-archive',
+      'test.jpeg' => 'application/octet-stream',
+      'test.jpg' => 'image/jpeg',
+      'test.jar.jpg' => 'image/jpeg',
+      'test.jpg.jar' => 'application/java-archive',
+      'test.pcf.z' => 'application/octet-stream',
+      'pcf.z' => 'application/octet-stream',
+      'jar' => 'application/octet-stream',
+      'some.junk' => 'application/octet-stream',
+      'foo.file_test_1' => 'application/octet-stream',
+      'foo.file_test_2' => 'application/octet-stream',
+      'foo.doc' => 'application/octet-stream',
+      'test.ogg' => 'application/octet-stream',
+    );
+
+    foreach ($test_case as $input => $expected) {
+      $output = file_get_mimetype($input, $mapping);
+      $this->assertIdentical($output, $expected, t('Mimetype (using passed-in mappings) for %input is %output (expected: %expected).', array('%input' => $input, '%output' => $output, '%expected' => $expected)));
+    }
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/NameMungingTest.php b/core/modules/system/lib/Drupal/system/Tests/File/NameMungingTest.php
new file mode 100644
index 0000000..926a34a
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/NameMungingTest.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\NameMungingTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Tests for file_munge_filename() and file_unmunge_filename().
+ */
+class NameMungingTest extends FileTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'File naming',
+      'description' => 'Test filename munging and unmunging.',
+      'group' => 'File API',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    $this->bad_extension = 'php';
+    $this->name = $this->randomName() . '.' . $this->bad_extension . '.txt';
+  }
+
+  /**
+   * Create a file and munge/unmunge the name.
+   */
+  function testMunging() {
+    // Disable insecure uploads.
+    variable_set('allow_insecure_uploads', 0);
+    $munged_name = file_munge_filename($this->name, '', TRUE);
+    $messages = drupal_get_messages();
+    $this->assertTrue(in_array(t('For security reasons, your upload has been renamed to %filename.', array('%filename' => $munged_name)), $messages['status']), t('Alert properly set when a file is renamed.'));
+    $this->assertNotEqual($munged_name, $this->name, t('The new filename (%munged) has been modified from the original (%original)', array('%munged' => $munged_name, '%original' => $this->name)));
+  }
+
+  /**
+   * If the allow_insecure_uploads variable evaluates to true, the file should
+   * come out untouched, no matter how evil the filename.
+   */
+  function testMungeIgnoreInsecure() {
+    variable_set('allow_insecure_uploads', 1);
+    $munged_name = file_munge_filename($this->name, '');
+    $this->assertIdentical($munged_name, $this->name, t('The original filename (%original) matches the munged filename (%munged) when insecure uploads are enabled.', array('%munged' => $munged_name, '%original' => $this->name)));
+  }
+
+  /**
+   * White listed extensions are ignored by file_munge_filename().
+   */
+  function testMungeIgnoreWhitelisted() {
+    // Declare our extension as whitelisted.
+    $munged_name = file_munge_filename($this->name, $this->bad_extension);
+    $this->assertIdentical($munged_name, $this->name, t('The new filename (%munged) matches the original (%original) once the extension has been whitelisted.', array('%munged' => $munged_name, '%original' => $this->name)));
+  }
+
+  /**
+   * Ensure that unmunge gets your name back.
+   */
+  function testUnMunge() {
+    $munged_name = file_munge_filename($this->name, '', FALSE);
+    $unmunged_name = file_unmunge_filename($munged_name);
+    $this->assertIdentical($unmunged_name, $this->name, t('The unmunged (%unmunged) filename matches the original (%original)', array('%unmunged' => $unmunged_name, '%original' => $this->name)));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileDirectoryTest.php b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileDirectoryTest.php
new file mode 100644
index 0000000..1a2ef48
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileDirectoryTest.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\RemoteFileDirectoryTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Directory related tests.
+ */
+class RemoteFileDirectoryTest extends DirectoryTest {
+  public static function getInfo() {
+    $info = parent::getInfo();
+    $info['group'] = 'File API (remote)';
+    return $info;
+  }
+
+  function setUp() {
+    parent::setUp('file_test');
+    variable_set('file_default_scheme', 'dummy-remote');
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileScanDirectoryTest.php b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileScanDirectoryTest.php
new file mode 100644
index 0000000..75fa904
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileScanDirectoryTest.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\RemoteFileScanDirectoryTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Tests the file_scan_directory() function on remote filesystems.
+ */
+class RemoteFileScanDirectoryTest extends ScanDirectoryTest {
+  public static function getInfo() {
+    $info = parent::getInfo();
+    $info['group'] = 'File API (remote)';
+    return $info;
+  }
+
+  function setUp() {
+    parent::setUp('file_test');
+    variable_set('file_default_scheme', 'dummy-remote');
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedCopyTest.php b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedCopyTest.php
new file mode 100644
index 0000000..5aff075
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedCopyTest.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\RemoteFileUnmanagedCopyTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Unmanaged copy related tests on remote filesystems.
+ */
+class RemoteFileUnmanagedCopyTest extends UnmanagedCopyTest {
+  public static function getInfo() {
+    $info = parent::getInfo();
+    $info['group'] = 'File API (remote)';
+    return $info;
+  }
+
+  function setUp() {
+    parent::setUp('file_test');
+    variable_set('file_default_scheme', 'dummy-remote');
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedDeleteRecursiveTest.php b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedDeleteRecursiveTest.php
new file mode 100644
index 0000000..081dc3d
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedDeleteRecursiveTest.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\RemoteFileUnmanagedDeleteRecursiveTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Deletion related tests on remote filesystems.
+ */
+class RemoteFileUnmanagedDeleteRecursiveTest extends UnmanagedDeleteRecursiveTest {
+  public static function getInfo() {
+    $info = parent::getInfo();
+    $info['group'] = 'File API (remote)';
+    return $info;
+  }
+
+  function setUp() {
+    parent::setUp('file_test');
+    variable_set('file_default_scheme', 'dummy-remote');
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedDeleteTest.php b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedDeleteTest.php
new file mode 100644
index 0000000..44dbf14
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedDeleteTest.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\RemoteFileUnmanagedDeleteTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Deletion related tests on remote filesystems.
+ */
+class RemoteFileUnmanagedDeleteTest extends UnmanagedDeleteTest {
+  public static function getInfo() {
+    $info = parent::getInfo();
+    $info['group'] = 'File API (remote)';
+    return $info;
+  }
+
+  function setUp() {
+    parent::setUp('file_test');
+    variable_set('file_default_scheme', 'dummy-remote');
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedMoveTest.php b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedMoveTest.php
new file mode 100644
index 0000000..fd53fd8
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedMoveTest.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\RemoteFileUnmanagedMoveTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Unmanaged move related tests on remote filesystems.
+ */
+class RemoteFileUnmanagedMoveTest extends UnmanagedMoveTest {
+  public static function getInfo() {
+    $info = parent::getInfo();
+    $info['group'] = 'File API (remote)';
+    return $info;
+  }
+
+  function setUp() {
+    parent::setUp('file_test');
+    variable_set('file_default_scheme', 'dummy-remote');
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedSaveDataTest.php b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedSaveDataTest.php
new file mode 100644
index 0000000..3463e6a
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/RemoteFileUnmanagedSaveDataTest.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\RemoteFileUnmanagedSaveDataTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Tests the file_unmanaged_save_data() function on remote filesystems.
+ */
+class RemoteFileUnmanagedSaveDataTest extends UnmanagedSaveDataTest {
+  public static function getInfo() {
+    $info = parent::getInfo();
+    $info['group'] = 'File API (remote)';
+    return $info;
+  }
+
+  function setUp() {
+    parent::setUp('file_test');
+    variable_set('file_default_scheme', 'dummy-remote');
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/ScanDirectoryTest.php b/core/modules/system/lib/Drupal/system/Tests/File/ScanDirectoryTest.php
new file mode 100644
index 0000000..dda40fd
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/ScanDirectoryTest.php
@@ -0,0 +1,139 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\ScanDirectoryTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Tests the file_scan_directory() function.
+ */
+class ScanDirectoryTest extends FileTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'File scan directory',
+      'description' => 'Tests the file_scan_directory() function.',
+      'group' => 'File API',
+    );
+  }
+
+  function setUp() {
+    parent::setUp(array('file_test'));
+    $this->path = drupal_get_path('module', 'simpletest') . '/files';
+  }
+
+  /**
+   * Check the format of the returned values.
+   */
+  function testReturn() {
+    // Grab a listing of all the JavaSscript files and check that they're
+    // passed to the callback.
+    $all_files = file_scan_directory($this->path, '/^javascript-/');
+    ksort($all_files);
+    $this->assertEqual(2, count($all_files), t('Found two, expected javascript files.'));
+
+    // Check the first file.
+    $file = reset($all_files);
+    $this->assertEqual(key($all_files), $file->uri, t('Correct array key was used for the first returned file.'));
+    $this->assertEqual($file->uri, $this->path . '/javascript-1.txt', t('First file name was set correctly.'));
+    $this->assertEqual($file->filename, 'javascript-1.txt', t('First basename was set correctly'));
+    $this->assertEqual($file->name, 'javascript-1', t('First name was set correctly.'));
+
+    // Check the second file.
+    $file = next($all_files);
+    $this->assertEqual(key($all_files), $file->uri, t('Correct array key was used for the second returned file.'));
+    $this->assertEqual($file->uri, $this->path . '/javascript-2.script', t('Second file name was set correctly.'));
+    $this->assertEqual($file->filename, 'javascript-2.script', t('Second basename was set correctly'));
+    $this->assertEqual($file->name, 'javascript-2', t('Second name was set correctly.'));
+  }
+
+  /**
+   * Check that the callback function is called correctly.
+   */
+  function testOptionCallback() {
+    drupal_load('module', 'file_test');
+
+    // When nothing is matched nothing should be passed to the callback.
+    $all_files = file_scan_directory($this->path, '/^NONEXISTINGFILENAME/', array('callback' => 'file_test_file_scan_callback'));
+    $this->assertEqual(0, count($all_files), t('No files were found.'));
+    $results = file_test_file_scan_callback();
+    file_test_file_scan_callback_reset();
+    $this->assertEqual(0, count($results), t('No files were passed to the callback.'));
+
+    // Grab a listing of all the JavaSscript files and check that they're
+    // passed to the callback.
+    $all_files = file_scan_directory($this->path, '/^javascript-/', array('callback' => 'file_test_file_scan_callback'));
+    $this->assertEqual(2, count($all_files), t('Found two, expected javascript files.'));
+    $results = file_test_file_scan_callback();
+    file_test_file_scan_callback_reset();
+    $this->assertEqual(2, count($results), t('Files were passed to the callback.'));
+  }
+
+  /**
+   * Check that the no-mask parameter is honored.
+   */
+  function testOptionNoMask() {
+    // Grab a listing of all the JavaSscript files.
+    $all_files = file_scan_directory($this->path, '/^javascript-/');
+    $this->assertEqual(2, count($all_files), t('Found two, expected javascript files.'));
+
+    // Now use the nomast parameter to filter out the .script file.
+    $filtered_files = file_scan_directory($this->path, '/^javascript-/', array('nomask' => '/.script$/'));
+    $this->assertEqual(1, count($filtered_files), t('Filtered correctly.'));
+  }
+
+  /**
+   * Check that key parameter sets the return value's key.
+   */
+  function testOptionKey() {
+    // "filename", for the path starting with $dir.
+    $expected = array($this->path . '/javascript-1.txt', $this->path . '/javascript-2.script');
+    $actual = array_keys(file_scan_directory($this->path, '/^javascript-/', array('key' => 'filepath')));
+    sort($actual);
+    $this->assertEqual($expected, $actual, t('Returned the correct values for the filename key.'));
+
+    // "basename", for the basename of the file.
+    $expected = array('javascript-1.txt', 'javascript-2.script');
+    $actual = array_keys(file_scan_directory($this->path, '/^javascript-/', array('key' => 'filename')));
+    sort($actual);
+    $this->assertEqual($expected, $actual, t('Returned the correct values for the basename key.'));
+
+    // "name" for the name of the file without an extension.
+    $expected = array('javascript-1', 'javascript-2');
+    $actual = array_keys(file_scan_directory($this->path, '/^javascript-/', array('key' => 'name')));
+    sort($actual);
+    $this->assertEqual($expected, $actual, t('Returned the correct values for the name key.'));
+
+    // Invalid option that should default back to "filename".
+    $expected = array($this->path . '/javascript-1.txt', $this->path . '/javascript-2.script');
+    $actual = array_keys(file_scan_directory($this->path, '/^javascript-/', array('key' => 'INVALID')));
+    sort($actual);
+    $this->assertEqual($expected, $actual, t('An invalid key defaulted back to the default.'));
+  }
+
+  /**
+   * Check that the recurse option decends into subdirectories.
+   */
+  function testOptionRecurse() {
+    $files = file_scan_directory(drupal_get_path('module', 'simpletest'), '/^javascript-/', array('recurse' => FALSE));
+    $this->assertTrue(empty($files), t("Without recursion couldn't find javascript files."));
+
+    $files = file_scan_directory(drupal_get_path('module', 'simpletest'), '/^javascript-/', array('recurse' => TRUE));
+    $this->assertEqual(2, count($files), t('With recursion we found the expected javascript files.'));
+  }
+
+
+  /**
+   * Check that the min_depth options lets us ignore files in the starting
+   * directory.
+   */
+  function testOptionMinDepth() {
+    $files = file_scan_directory($this->path, '/^javascript-/', array('min_depth' => 0));
+    $this->assertEqual(2, count($files), t('No minimum-depth gets files in current directory.'));
+
+    $files = file_scan_directory($this->path, '/^javascript-/', array('min_depth' => 1));
+    $this->assertTrue(empty($files), t("Minimum-depth of 1 successfully excludes files from current directory."));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/StreamWrapperTest.php b/core/modules/system/lib/Drupal/system/Tests/File/StreamWrapperTest.php
new file mode 100644
index 0000000..5a4d58d
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/StreamWrapperTest.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\StreamWrapperTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests stream wrapper functions.
+ */
+class StreamWrapperTest extends WebTestBase {
+
+  protected $scheme = 'dummy';
+  protected $classname = 'Drupal\file_test\DummyStreamWrapper';
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Stream wrappers',
+      'description' => 'Tests stream wrapper functions.',
+      'group' => 'File API',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('file_test');
+    drupal_static_reset('file_get_stream_wrappers');
+  }
+
+  function tearDown() {
+    parent::tearDown();
+    stream_wrapper_unregister($this->scheme);
+  }
+
+  /**
+   * Test the getClassName() function.
+   */
+  function testGetClassName() {
+    // Check the dummy scheme.
+    $this->assertEqual($this->classname, file_stream_wrapper_get_class($this->scheme), t('Got correct class name for dummy scheme.'));
+    // Check core's scheme.
+    $this->assertEqual('Drupal\Core\StreamWrapper\PublicStream', file_stream_wrapper_get_class('public'), t('Got correct class name for public scheme.'));
+  }
+
+  /**
+   * Test the file_stream_wrapper_get_instance_by_scheme() function.
+   */
+  function testGetInstanceByScheme() {
+    $instance = file_stream_wrapper_get_instance_by_scheme($this->scheme);
+    $this->assertEqual($this->classname, get_class($instance), t('Got correct class type for dummy scheme.'));
+
+    $instance = file_stream_wrapper_get_instance_by_scheme('public');
+    $this->assertEqual('Drupal\Core\StreamWrapper\PublicStream', get_class($instance), t('Got correct class type for public scheme.'));
+  }
+
+  /**
+   * Test the URI and target functions.
+   */
+  function testUriFunctions() {
+    $instance = file_stream_wrapper_get_instance_by_uri($this->scheme . '://foo');
+    $this->assertEqual($this->classname, get_class($instance), t('Got correct class type for dummy URI.'));
+
+    $instance = file_stream_wrapper_get_instance_by_uri('public://foo');
+    $this->assertEqual('Drupal\Core\StreamWrapper\PublicStream', get_class($instance), t('Got correct class type for public URI.'));
+
+    // Test file_uri_target().
+    $this->assertEqual(file_uri_target('public://foo/bar.txt'), 'foo/bar.txt', t('Got a valid stream target from public://foo/bar.txt.'));
+    $this->assertFalse(file_uri_target('foo/bar.txt'), t('foo/bar.txt is not a valid stream.'));
+
+    // Test file_build_uri() and
+    // Drupal\Core\StreamWrapper\LocalStream::getDirectoryPath().
+    $this->assertEqual(file_build_uri('foo/bar.txt'), 'public://foo/bar.txt', t('Expected scheme was added.'));
+    $this->assertEqual(file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath(), variable_get('file_public_path'), t('Expected default directory path was returned.'));
+    $this->assertEqual(file_stream_wrapper_get_instance_by_scheme('temporary')->getDirectoryPath(), variable_get('file_temporary_path'), t('Expected temporary directory path was returned.'));
+
+    variable_set('file_default_scheme', 'private');
+    $this->assertEqual(file_build_uri('foo/bar.txt'), 'private://foo/bar.txt', t('Got a valid URI from foo/bar.txt.'));
+  }
+
+  /**
+   * Test the scheme functions.
+   */
+  function testGetValidStreamScheme() {
+    $this->assertEqual('foo', file_uri_scheme('foo://pork//chops'), t('Got the correct scheme from foo://asdf'));
+    $this->assertTrue(file_stream_wrapper_valid_scheme(file_uri_scheme('public://asdf')), t('Got a valid stream scheme from public://asdf'));
+    $this->assertFalse(file_stream_wrapper_valid_scheme(file_uri_scheme('foo://asdf')), t('Did not get a valid stream scheme from foo://asdf'));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedCopyTest.php b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedCopyTest.php
new file mode 100644
index 0000000..c4a44f9
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedCopyTest.php
@@ -0,0 +1,96 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\UnmanagedCopyTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Unmanaged copy related tests.
+ */
+class UnmanagedCopyTest extends FileTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Unmanaged file copying',
+      'description' => 'Tests the unmanaged file copy function.',
+      'group' => 'File API',
+    );
+  }
+
+  /**
+   * Copy a normal file.
+   */
+  function testNormal() {
+    // Create a file for testing
+    $uri = $this->createUri();
+
+    // Copying to a new name.
+    $desired_filepath = 'public://' . $this->randomName();
+    $new_filepath = file_unmanaged_copy($uri, $desired_filepath, FILE_EXISTS_ERROR);
+    $this->assertTrue($new_filepath, t('Copy was successful.'));
+    $this->assertEqual($new_filepath, $desired_filepath, t('Returned expected filepath.'));
+    $this->assertTrue(file_exists($uri), t('Original file remains.'));
+    $this->assertTrue(file_exists($new_filepath), t('New file exists.'));
+    $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
+
+    // Copying with rename.
+    $desired_filepath = 'public://' . $this->randomName();
+    $this->assertTrue(file_put_contents($desired_filepath, ' '), t('Created a file so a rename will have to happen.'));
+    $newer_filepath = file_unmanaged_copy($uri, $desired_filepath, FILE_EXISTS_RENAME);
+    $this->assertTrue($newer_filepath, t('Copy was successful.'));
+    $this->assertNotEqual($newer_filepath, $desired_filepath, t('Returned expected filepath.'));
+    $this->assertTrue(file_exists($uri), t('Original file remains.'));
+    $this->assertTrue(file_exists($newer_filepath), t('New file exists.'));
+    $this->assertFilePermissions($newer_filepath, variable_get('file_chmod_file', 0664));
+
+    // TODO: test copying to a directory (rather than full directory/file path)
+    // TODO: test copying normal files using normal paths (rather than only streams)
+  }
+
+  /**
+   * Copy a non-existent file.
+   */
+  function testNonExistent() {
+    // Copy non-existent file
+    $desired_filepath = $this->randomName();
+    $this->assertFalse(file_exists($desired_filepath), t("Randomly named file doesn't exists."));
+    $new_filepath = file_unmanaged_copy($desired_filepath, $this->randomName());
+    $this->assertFalse($new_filepath, t('Copying a missing file fails.'));
+  }
+
+  /**
+   * Copy a file onto itself.
+   */
+  function testOverwriteSelf() {
+    // Create a file for testing
+    $uri = $this->createUri();
+
+    // Copy the file onto itself with renaming works.
+    $new_filepath = file_unmanaged_copy($uri, $uri, FILE_EXISTS_RENAME);
+    $this->assertTrue($new_filepath, t('Copying onto itself with renaming works.'));
+    $this->assertNotEqual($new_filepath, $uri, t('Copied file has a new name.'));
+    $this->assertTrue(file_exists($uri), t('Original file exists after copying onto itself.'));
+    $this->assertTrue(file_exists($new_filepath), t('Copied file exists after copying onto itself.'));
+    $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
+
+    // Copy the file onto itself without renaming fails.
+    $new_filepath = file_unmanaged_copy($uri, $uri, FILE_EXISTS_ERROR);
+    $this->assertFalse($new_filepath, t('Copying onto itself without renaming fails.'));
+    $this->assertTrue(file_exists($uri), t('File exists after copying onto itself.'));
+
+    // Copy the file into same directory without renaming fails.
+    $new_filepath = file_unmanaged_copy($uri, drupal_dirname($uri), FILE_EXISTS_ERROR);
+    $this->assertFalse($new_filepath, t('Copying onto itself fails.'));
+    $this->assertTrue(file_exists($uri), t('File exists after copying onto itself.'));
+
+    // Copy the file into same directory with renaming works.
+    $new_filepath = file_unmanaged_copy($uri, drupal_dirname($uri), FILE_EXISTS_RENAME);
+    $this->assertTrue($new_filepath, t('Copying into same directory works.'));
+    $this->assertNotEqual($new_filepath, $uri, t('Copied file has a new name.'));
+    $this->assertTrue(file_exists($uri), t('Original file exists after copying onto itself.'));
+    $this->assertTrue(file_exists($new_filepath), t('Copied file exists after copying onto itself.'));
+    $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedDeleteRecursiveTest.php b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedDeleteRecursiveTest.php
new file mode 100644
index 0000000..77fecb2
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedDeleteRecursiveTest.php
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\UnmanagedDeleteRecursiveTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Deletion related tests.
+ */
+class UnmanagedDeleteRecursiveTest extends FileTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Unmanaged recursive file delete',
+      'description' => 'Tests the unmanaged file delete recursive function.',
+      'group' => 'File API',
+    );
+  }
+
+  /**
+   * Delete a normal file.
+   */
+  function testSingleFile() {
+    // Create a file for testing
+    $filepath = file_default_scheme() . '://' . $this->randomName();
+    file_put_contents($filepath, '');
+
+    // Delete the file.
+    $this->assertTrue(file_unmanaged_delete_recursive($filepath), t('Function reported success.'));
+    $this->assertFalse(file_exists($filepath), t('Test file has been deleted.'));
+  }
+
+  /**
+   * Try deleting an empty directory.
+   */
+  function testEmptyDirectory() {
+    // A directory to operate on.
+    $directory = $this->createDirectory();
+
+    // Delete the directory.
+    $this->assertTrue(file_unmanaged_delete_recursive($directory), t('Function reported success.'));
+    $this->assertFalse(file_exists($directory), t('Directory has been deleted.'));
+  }
+
+  /**
+   * Try deleting a directory with some files.
+   */
+  function testDirectory() {
+    // A directory to operate on.
+    $directory = $this->createDirectory();
+    $filepathA = $directory . '/A';
+    $filepathB = $directory . '/B';
+    file_put_contents($filepathA, '');
+    file_put_contents($filepathB, '');
+
+    // Delete the directory.
+    $this->assertTrue(file_unmanaged_delete_recursive($directory), t('Function reported success.'));
+    $this->assertFalse(file_exists($filepathA), t('Test file A has been deleted.'));
+    $this->assertFalse(file_exists($filepathB), t('Test file B has been deleted.'));
+    $this->assertFalse(file_exists($directory), t('Directory has been deleted.'));
+  }
+
+  /**
+   * Try deleting subdirectories with some files.
+   */
+  function testSubDirectory() {
+    // A directory to operate on.
+    $directory = $this->createDirectory();
+    $subdirectory = $this->createDirectory($directory . '/sub');
+    $filepathA = $directory . '/A';
+    $filepathB = $subdirectory . '/B';
+    file_put_contents($filepathA, '');
+    file_put_contents($filepathB, '');
+
+    // Delete the directory.
+    $this->assertTrue(file_unmanaged_delete_recursive($directory), t('Function reported success.'));
+    $this->assertFalse(file_exists($filepathA), t('Test file A has been deleted.'));
+    $this->assertFalse(file_exists($filepathB), t('Test file B has been deleted.'));
+    $this->assertFalse(file_exists($subdirectory), t('Subdirectory has been deleted.'));
+    $this->assertFalse(file_exists($directory), t('Directory has been deleted.'));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedDeleteTest.php b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedDeleteTest.php
new file mode 100644
index 0000000..8ecd1ae
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedDeleteTest.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\UnmanagedDeleteTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Deletion related tests.
+ */
+class UnmanagedDeleteTest extends FileTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Unmanaged file delete',
+      'description' => 'Tests the unmanaged file delete function.',
+      'group' => 'File API',
+    );
+  }
+
+  /**
+   * Delete a normal file.
+   */
+  function testNormal() {
+    // Create a file for testing
+    $uri = $this->createUri();
+
+    // Delete a regular file
+    $this->assertTrue(file_unmanaged_delete($uri), t('Deleted worked.'));
+    $this->assertFalse(file_exists($uri), t('Test file has actually been deleted.'));
+  }
+
+  /**
+   * Try deleting a missing file.
+   */
+  function testMissing() {
+    // Try to delete a non-existing file
+    $this->assertTrue(file_unmanaged_delete(file_default_scheme() . '/' . $this->randomName()), t('Returns true when deleting a non-existent file.'));
+  }
+
+  /**
+   * Try deleting a directory.
+   */
+  function testDirectory() {
+    // A directory to operate on.
+    $directory = $this->createDirectory();
+
+    // Try to delete a directory
+    $this->assertFalse(file_unmanaged_delete($directory), t('Could not delete the delete directory.'));
+    $this->assertTrue(file_exists($directory), t('Directory has not been deleted.'));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedMoveTest.php b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedMoveTest.php
new file mode 100644
index 0000000..1090aaa
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedMoveTest.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\UnmanagedMoveTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Unmanaged move related tests.
+ */
+class UnmanagedMoveTest extends FileTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Unmanaged file moving',
+      'description' => 'Tests the unmanaged file move function.',
+      'group' => 'File API',
+    );
+  }
+
+  /**
+   * Move a normal file.
+   */
+  function testNormal() {
+    // Create a file for testing
+    $uri = $this->createUri();
+
+    // Moving to a new name.
+    $desired_filepath = 'public://' . $this->randomName();
+    $new_filepath = file_unmanaged_move($uri, $desired_filepath, FILE_EXISTS_ERROR);
+    $this->assertTrue($new_filepath, t('Move was successful.'));
+    $this->assertEqual($new_filepath, $desired_filepath, t('Returned expected filepath.'));
+    $this->assertTrue(file_exists($new_filepath), t('File exists at the new location.'));
+    $this->assertFalse(file_exists($uri), t('No file remains at the old location.'));
+    $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
+
+    // Moving with rename.
+    $desired_filepath = 'public://' . $this->randomName();
+    $this->assertTrue(file_exists($new_filepath), t('File exists before moving.'));
+    $this->assertTrue(file_put_contents($desired_filepath, ' '), t('Created a file so a rename will have to happen.'));
+    $newer_filepath = file_unmanaged_move($new_filepath, $desired_filepath, FILE_EXISTS_RENAME);
+    $this->assertTrue($newer_filepath, t('Move was successful.'));
+    $this->assertNotEqual($newer_filepath, $desired_filepath, t('Returned expected filepath.'));
+    $this->assertTrue(file_exists($newer_filepath), t('File exists at the new location.'));
+    $this->assertFalse(file_exists($new_filepath), t('No file remains at the old location.'));
+    $this->assertFilePermissions($newer_filepath, variable_get('file_chmod_file', 0664));
+
+    // TODO: test moving to a directory (rather than full directory/file path)
+    // TODO: test creating and moving normal files (rather than streams)
+  }
+
+  /**
+   * Try to move a missing file.
+   */
+  function testMissing() {
+    // Move non-existent file.
+    $new_filepath = file_unmanaged_move($this->randomName(), $this->randomName());
+    $this->assertFalse($new_filepath, t('Moving a missing file fails.'));
+  }
+
+  /**
+   * Try to move a file onto itself.
+   */
+  function testOverwriteSelf() {
+    // Create a file for testing.
+    $uri = $this->createUri();
+
+    // Move the file onto itself without renaming shouldn't make changes.
+    $new_filepath = file_unmanaged_move($uri, $uri, FILE_EXISTS_REPLACE);
+    $this->assertFalse($new_filepath, t('Moving onto itself without renaming fails.'));
+    $this->assertTrue(file_exists($uri), t('File exists after moving onto itself.'));
+
+    // Move the file onto itself with renaming will result in a new filename.
+    $new_filepath = file_unmanaged_move($uri, $uri, FILE_EXISTS_RENAME);
+    $this->assertTrue($new_filepath, t('Moving onto itself with renaming works.'));
+    $this->assertFalse(file_exists($uri), t('Original file has been removed.'));
+    $this->assertTrue(file_exists($new_filepath), t('File exists after moving onto itself.'));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedSaveDataTest.php b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedSaveDataTest.php
new file mode 100644
index 0000000..6494b86
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedSaveDataTest.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\UnmanagedSaveDataTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Tests the file_unmanaged_save_data() function.
+ */
+class UnmanagedSaveDataTest extends FileTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Unmanaged file save data',
+      'description' => 'Tests the unmanaged file save data function.',
+      'group' => 'File API',
+    );
+  }
+
+  /**
+   * Test the file_unmanaged_save_data() function.
+   */
+  function testFileSaveData() {
+    $contents = $this->randomName(8);
+
+    // No filename.
+    $filepath = file_unmanaged_save_data($contents);
+    $this->assertTrue($filepath, t('Unnamed file saved correctly.'));
+    $this->assertEqual(file_uri_scheme($filepath), file_default_scheme(), t("File was placed in Drupal's files directory."));
+    $this->assertEqual($contents, file_get_contents($filepath), t('Contents of the file are correct.'));
+
+    // Provide a filename.
+    $filepath = file_unmanaged_save_data($contents, 'public://asdf.txt', FILE_EXISTS_REPLACE);
+    $this->assertTrue($filepath, t('Unnamed file saved correctly.'));
+    $this->assertEqual('asdf.txt', drupal_basename($filepath), t('File was named correctly.'));
+    $this->assertEqual($contents, file_get_contents($filepath), t('Contents of the file are correct.'));
+    $this->assertFilePermissions($filepath, variable_get('file_chmod_file', 0664));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/UrlRewritingTest.php b/core/modules/system/lib/Drupal/system/Tests/File/UrlRewritingTest.php
new file mode 100644
index 0000000..fe608b7
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/File/UrlRewritingTest.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\File\UrlRewritingTest.
+ */
+
+namespace Drupal\system\Tests\File;
+
+/**
+ * Tests for file URL rewriting.
+ */
+class UrlRewritingTest extends FileTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'File URL rewriting',
+      'description' => 'Tests for file URL rewriting.',
+      'group' => 'File',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('file_test');
+  }
+
+  /**
+   * Test the generating of rewritten shipped file URLs.
+   */
+  function testShippedFileURL()  {
+    // 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).
+
+    // Test alteration of file URLs to use a CDN.
+    variable_set('file_test_hook_file_url_alter', 'cdn');
+    $filepath = 'core/misc/jquery.js';
+    $url = file_create_url($filepath);
+    $this->assertEqual(FILE_URL_TEST_CDN_1 . '/' . $filepath, $url, t('Correctly generated a CDN URL for a shipped file.'));
+    $filepath = 'core/misc/favicon.ico';
+    $url = file_create_url($filepath);
+    $this->assertEqual(FILE_URL_TEST_CDN_2 . '/' . $filepath, $url, t('Correctly generated a CDN URL for a shipped file.'));
+
+    // Test alteration of file URLs to use root-relative URLs.
+    variable_set('file_test_hook_file_url_alter', 'root-relative');
+    $filepath = 'core/misc/jquery.js';
+    $url = file_create_url($filepath);
+    $this->assertEqual(base_path() . '/' . $filepath, $url, t('Correctly generated a root-relative URL for a shipped file.'));
+    $filepath = 'core/misc/favicon.ico';
+    $url = file_create_url($filepath);
+    $this->assertEqual(base_path() . '/' . $filepath, $url, t('Correctly generated a root-relative URL for a shipped file.'));
+
+    // Test alteration of file URLs to use protocol-relative URLs.
+    variable_set('file_test_hook_file_url_alter', 'protocol-relative');
+    $filepath = 'core/misc/jquery.js';
+    $url = file_create_url($filepath);
+    $this->assertEqual('/' . base_path() . '/' . $filepath, $url, t('Correctly generated a protocol-relative URL for a shipped file.'));
+    $filepath = 'core/misc/favicon.ico';
+    $url = file_create_url($filepath);
+    $this->assertEqual('/' . base_path() . '/' . $filepath, $url, t('Correctly generated a protocol-relative URL for a shipped file.'));
+  }
+
+  /**
+   * Test the generating of rewritten public created file URLs.
+   */
+  function testPublicCreatedFileURL() {
+    // Test generating an URL to a created file.
+
+    // Test alteration of file URLs to use a CDN.
+    variable_set('file_test_hook_file_url_alter', 'cdn');
+    $uri = $this->createUri();
+    $url = file_create_url($uri);
+    $public_directory_path = file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath();
+    $this->assertEqual(FILE_URL_TEST_CDN_2 . '/' . $public_directory_path . '/' . drupal_basename($uri), $url, t('Correctly generated a CDN URL for a created file.'));
+
+    // Test alteration of file URLs to use root-relative URLs.
+    variable_set('file_test_hook_file_url_alter', 'root-relative');
+    $uri = $this->createUri();
+    $url = file_create_url($uri);
+    $this->assertEqual(base_path() . '/' . $public_directory_path . '/' . drupal_basename($uri), $url, t('Correctly generated a root-relative URL for a created file.'));
+
+    // Test alteration of file URLs to use a protocol-relative URLs.
+    variable_set('file_test_hook_file_url_alter', 'protocol-relative');
+    $uri = $this->createUri();
+    $url = file_create_url($uri);
+    $this->assertEqual('/' . base_path() . '/' . $public_directory_path . '/' . drupal_basename($uri), $url, t('Correctly generated a protocol-relative URL for a created file.'));
+  }
+}
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 9ad2ba1..373a7d1 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -6,7 +6,6 @@
  */
 
 use Drupal\Core\Utility\UpdateException;
-use Drupal\Core\File\File;
 
 /**
  * @addtogroup hooks
@@ -2266,163 +2265,6 @@ function hook_stream_wrappers_alter(&$wrappers) {
 }
 
 /**
- * Load additional information into file entities.
- *
- * file_load_multiple() calls this hook to allow modules to load
- * additional information into each file.
- *
- * @param $files
- *   An array of file entities, indexed by fid.
- *
- * @see file_load_multiple()
- * @see file_load()
- */
-function hook_file_load($files) {
-  // Add the upload specific data into the file entity.
-  $result = db_query('SELECT * FROM {upload} u WHERE u.fid IN (:fids)', array(':fids' => array_keys($files)))->fetchAll(PDO::FETCH_ASSOC);
-  foreach ($result as $record) {
-    foreach ($record as $key => $value) {
-      $files[$record['fid']]->$key = $value;
-    }
-  }
-}
-
-/**
- * Check that files meet a given criteria.
- *
- * This hook lets modules perform additional validation on files. They're able
- * to report a failure by returning one or more error messages.
- *
- * @param Drupal\Core\File\File $file
- *   The file entity being validated.
- * @return
- *   An array of error messages. If there are no problems with the file return
- *   an empty array.
- *
- * @see file_validate()
- */
-function hook_file_validate(Drupal\Core\File\File $file) {
-  $errors = array();
-
-  if (empty($file->filename)) {
-    $errors[] = t("The file's name is empty. Please give a name to the file.");
-  }
-  if (strlen($file->filename) > 255) {
-    $errors[] = t("The file's name exceeds the 255 characters limit. Please rename the file and try again.");
-  }
-
-  return $errors;
-}
-
-/**
- * Act on a file being inserted or updated.
- *
- * This hook is called when a file has been added to the database. The hook
- * doesn't distinguish between files created as a result of a copy or those
- * created by an upload.
- *
- * @param Drupal\Core\File\File $file
- *   The file entity that is about to be created or updated.
- */
-function hook_file_presave(Drupal\Core\File\File $file) {
-  // Change the file timestamp to an hour prior.
-  $file->timestamp -= 3600;
-}
-
-/**
- * Respond to a file being added.
- *
- * This hook is called after a file has been added to the database. The hook
- * doesn't distinguish between files created as a result of a copy or those
- * created by an upload.
- *
- * @param Drupal\Core\File\File $file
- *   The file that has been added.
- */
-function hook_file_insert(Drupal\Core\File\File $file) {
-  // Add a message to the log, if the file is a jpg
-  $validate = file_validate_extensions($file, 'jpg');
-  if (empty($validate)) {
-    watchdog('file', 'A jpg has been added.');
-  }
-}
-
-/**
- * Respond to a file being updated.
- *
- * This hook is called when an existing file is saved.
- *
- * @param Drupal\Core\File\File $file
- *   The file that has just been updated.
- */
-function hook_file_update(Drupal\Core\File\File $file) {
-
-}
-
-/**
- * Respond to a file that has been copied.
- *
- * @param Drupal\Core\File\File $file
- *   The newly copied file entity.
- * @param Drupal\Core\File\File $source
- *   The original file before the copy.
- *
- * @see file_copy()
- */
-function hook_file_copy(Drupal\Core\File\File $file, Drupal\Core\File\File $source) {
-
-}
-
-/**
- * Respond to a file that has been moved.
- *
- * @param Drupal\Core\File\File $file
- *   The updated file entity after the move.
- * @param Drupal\Core\File\File $source
- *   The original file entity before the move.
- *
- * @see file_move()
- */
-function hook_file_move(Drupal\Core\File\File $file, Drupal\Core\File\File $source) {
-
-}
-
-/**
- * Act prior to file deletion.
- *
- * This hook is invoked when deleting a file before the file is removed from the
- * filesystem and before its records are removed from the database.
- *
- * @param Drupal\Core\File\File $file
- *   The file that is about to be deleted.
- *
- * @see hook_file_delete()
- * @see Drupal\Core\File\FileStorageController::delete()
- * @see upload_file_delete()
- */
-function hook_file_predelete(Drupal\Core\File\File $file) {
-  // Delete all information associated with the file.
-  db_delete('upload')->condition('fid', $file->fid)->execute();
-}
-
-/**
- * Respond to file deletion.
- *
- * This hook is invoked after the file has been removed from
- * the filesystem and after its records have been removed from the database.
- *
- * @param Drupal\Core\File\File $file
- *   The file that has just been deleted.
- *
- * @see hook_file_predelete()
- * @see Drupal\Core\File\FileStorageController::delete()
- */
-function hook_file_delete(Drupal\Core\File\File $file) {
-  // Delete all information associated with the file.
-  db_delete('upload')->condition('fid', $file->fid)->execute();
-}
-
-/**
  * Control access to private file downloads and specify HTTP headers.
  *
  * This hook allows modules enforce permissions on file downloads when the
diff --git a/core/modules/system/system.info b/core/modules/system/system.info
index d11422e..ce9aec4 100644
--- a/core/modules/system/system.info
+++ b/core/modules/system/system.info
@@ -11,7 +11,6 @@ configure = admin/config/system
 files[] = tests/cache.test
 files[] = tests/common.test
 files[] = tests/database.test
-files[] = tests/file.test
 files[] = tests/filetransfer.test
 files[] = tests/form.test
 files[] = tests/image.test
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 9ba7c4c..4165a78 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -857,137 +857,6 @@ function system_schema() {
     'primary key' => array('type', 'language'),
   );
 
-  $schema['file_managed'] = array(
-    'description' => 'Stores information for uploaded files.',
-    'fields' => array(
-      'fid' => array(
-        'description' => 'File ID.',
-        'type' => 'serial',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-      ),
-      'uid' => array(
-        'description' => 'The {users}.uid of the user who is associated with the file.',
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'filename' => array(
-        'description' => 'Name of the file with no path components. This may differ from the basename of the URI if the file is renamed to avoid overwriting an existing file.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-        'binary' => TRUE,
-      ),
-      'uri' => array(
-        'description' => 'The URI to access the file (either local or remote).',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-        'binary' => TRUE,
-      ),
-      'langcode' => array(
-        'description' => 'The {language}.langcode of this file.',
-        'type' => 'varchar',
-        'length' => 12,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'filemime' => array(
-        'description' => "The file's MIME type.",
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'filesize' => array(
-        'description' => 'The size of the file in bytes.',
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'status' => array(
-        'description' => 'A field indicating the status of the file. Two status are defined in core: temporary (0) and permanent (1). Temporary files older than DRUPAL_MAXIMUM_TEMP_FILE_AGE will be removed during a cron run.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'size' => 'tiny',
-      ),
-      'timestamp' => array(
-        'description' => 'UNIX timestamp for when the file was added.',
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-    ),
-    'indexes' => array(
-      'uid' => array('uid'),
-      'status' => array('status'),
-      'timestamp' => array('timestamp'),
-    ),
-    'unique keys' => array(
-      'uri' => array('uri'),
-    ),
-    'primary key' => array('fid'),
-    'foreign keys' => array(
-      'file_owner' => array(
-        'table' => 'users',
-        'columns' => array('uid' => 'uid'),
-      ),
-    ),
-  );
-
-  $schema['file_usage'] = array(
-    'description' => 'Track where a file is used.',
-    'fields' => array(
-      'fid' => array(
-        'description' => 'File ID.',
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-      ),
-      'module' => array(
-        'description' => 'The name of the module that is using the file.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'type' => array(
-        'description' => 'The name of the object type in which the file is used.',
-        'type' => 'varchar',
-        'length' => 64,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'id' => array(
-        'description' => 'The primary key of the object using the file.',
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'count' => array(
-        'description' => 'The number of times this file is used by this object.',
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-    ),
-    'primary key' => array('fid', 'type', 'id', 'module'),
-    'indexes' => array(
-      'type_id' => array('type', 'id'),
-      'fid_count' => array('fid', 'count'),
-      'fid_module' => array('fid', 'module'),
-    ),
-  );
-
   $schema['flood'] = array(
     'description' => 'Flood controls the threshold of events, such as the number of contact attempts.',
     'fields' => array(
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 73236f7..90b2aa0 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -264,25 +264,6 @@ function system_hook_info() {
 }
 
 /**
- * Implements hook_entity_info().
- */
-function system_entity_info() {
-  return array(
-    'file' => array(
-      'label' => t('File'),
-      'base table' => 'file_managed',
-      'controller class' => 'Drupal\Core\File\FileStorageController',
-      'entity class' => 'Drupal\Core\File\File',
-      'entity keys' => array(
-        'id' => 'fid',
-        'label' => 'filename',
-      ),
-      'static cache' => FALSE,
-    ),
-  );
-}
-
-/**
  * Implements hook_element_info().
  */
 function system_element_info() {
@@ -3085,30 +3066,6 @@ function system_cron() {
     ->condition('expiration', REQUEST_TIME, '<')
     ->execute();
 
-  // Remove temporary files that are older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
-  // Use separate placeholders for the status to avoid a bug in some versions
-  // of PHP. See http://drupal.org/node/352956.
-  $result = db_query('SELECT fid FROM {file_managed} WHERE status <> :permanent AND timestamp < :timestamp', array(
-    ':permanent' => FILE_STATUS_PERMANENT,
-    ':timestamp' => REQUEST_TIME - DRUPAL_MAXIMUM_TEMP_FILE_AGE
-  ));
-  foreach ($result as $row) {
-    if ($file = file_load($row->fid)) {
-      $references = file_usage_list($file);
-      if (empty($references)) {
-        if (file_exists($file->uri)) {
-          $file->delete();
-        }
-        else {
-          watchdog('file system', 'Could not delete temporary file "%path" during garbage collection', array('%path' => $file->uri), WATCHDOG_ERROR);
-        }
-      }
-      else {
-        watchdog('file system', 'Did not delete temporary file "%path" during garbage collection because it is in use by the following modules: %modules.', array('%path' => $file->uri, '%modules' => implode(', ', array_keys($references))), WATCHDOG_INFO);
-      }
-    }
-  }
-
   $cache_bins = array_merge(module_invoke_all('cache_flush'), array('form', 'menu'));
   foreach ($cache_bins as $bin) {
     cache($bin)->expire();
diff --git a/core/modules/system/tests/file.test b/core/modules/system/tests/file.test
deleted file mode 100644
index 34b9d77..0000000
--- a/core/modules/system/tests/file.test
+++ /dev/null
@@ -1,2807 +0,0 @@
-<?php
-
-/**
- *  @file
- *  This provides SimpleTests for the core file handling functionality.
- *  These include FileValidateTest and FileSaveTest.
- */
-
-use Drupal\simpletest\WebTestBase;
-use Drupal\Core\File\File;
-
-/**
- * Helper validator that returns the $errors parameter.
- */
-function file_test_validator(File $file, $errors) {
-  return $errors;
-}
-
-/**
- * Helper function for testing file_scan_directory().
- *
- * Each time the function is called the file is stored in a static variable.
- * When the function is called with no $filepath parameter, the results are
- * returned.
- *
- * @param $filepath
- *   File path
- * @return
- *   If $filepath is NULL, an array of all previous $filepath parameters
- */
-function file_test_file_scan_callback($filepath = NULL) {
-  $files = &drupal_static(__FUNCTION__, array());
-  if (isset($filepath)) {
-    $files[] = $filepath;
-  }
-  else {
-    return $files;
-  }
-}
-
-/**
- * Reset static variables used by file_test_file_scan_callback().
- */
-function file_test_file_scan_callback_reset() {
-  drupal_static_reset('file_test_file_scan_callback');
-}
-
-/**
- * Base class for file tests that adds some additional file specific
- * assertions and helper functions.
- */
-class FileTestCase extends WebTestBase {
-
-  function setUp() {
-    $modules = func_get_args();
-    $modules = (isset($modules[0]) && is_array($modules[0]) ? $modules[0] : $modules);
-    parent::setUp($modules);
-
-    // Make sure that custom stream wrappers are registered.
-    // @todo This has the potential to be a major bug deeply buried in File API;
-    //   file_unmanaged_*() API functions and test functions are invoking native
-    //   PHP functions directly, whereas Drupal's custom stream wrappers are not
-    //   registered yet.
-    file_get_stream_wrappers();
-  }
-
-  /**
-   * Check that two files have the same values for all fields other than the
-   * timestamp.
-   *
-   * @param $before
-   *   File object to compare.
-   * @param $after
-   *   File object to compare.
-   */
-  function assertFileUnchanged($before, $after) {
-    $this->assertEqual($before->fid, $after->fid, t('File id is the same: %file1 == %file2.', array('%file1' => $before->fid, '%file2' => $after->fid)), 'File unchanged');
-    $this->assertEqual($before->uid, $after->uid, t('File owner is the same: %file1 == %file2.', array('%file1' => $before->uid, '%file2' => $after->uid)), 'File unchanged');
-    $this->assertEqual($before->filename, $after->filename, t('File name is the same: %file1 == %file2.', array('%file1' => $before->filename, '%file2' => $after->filename)), 'File unchanged');
-    $this->assertEqual($before->uri, $after->uri, t('File path is the same: %file1 == %file2.', array('%file1' => $before->uri, '%file2' => $after->uri)), 'File unchanged');
-    $this->assertEqual($before->filemime, $after->filemime, t('File MIME type is the same: %file1 == %file2.', array('%file1' => $before->filemime, '%file2' => $after->filemime)), 'File unchanged');
-    $this->assertEqual($before->filesize, $after->filesize, t('File size is the same: %file1 == %file2.', array('%file1' => $before->filesize, '%file2' => $after->filesize)), 'File unchanged');
-    $this->assertEqual($before->status, $after->status, t('File status is the same: %file1 == %file2.', array('%file1' => $before->status, '%file2' => $after->status)), 'File unchanged');
-  }
-
-  /**
-   * Check that two files are not the same by comparing the fid and filepath.
-   *
-   * @param $file1
-   *   File object to compare.
-   * @param $file2
-   *   File object to compare.
-   */
-  function assertDifferentFile($file1, $file2) {
-    $this->assertNotEqual($file1->fid, $file2->fid, t('Files have different ids: %file1 != %file2.', array('%file1' => $file1->fid, '%file2' => $file2->fid)), 'Different file');
-    $this->assertNotEqual($file1->uri, $file2->uri, t('Files have different paths: %file1 != %file2.', array('%file1' => $file1->uri, '%file2' => $file2->uri)), 'Different file');
-  }
-
-  /**
-   * Check that two files are the same by comparing the fid and filepath.
-   *
-   * @param $file1
-   *   File object to compare.
-   * @param $file2
-   *   File object to compare.
-   */
-  function assertSameFile($file1, $file2) {
-    $this->assertEqual($file1->fid, $file2->fid, t('Files have the same ids: %file1 == %file2.', array('%file1' => $file1->fid, '%file2-fid' => $file2->fid)), 'Same file');
-    $this->assertEqual($file1->uri, $file2->uri, t('Files have the same path: %file1 == %file2.', array('%file1' => $file1->uri, '%file2' => $file2->uri)), 'Same file');
-  }
-
-  /**
-   * Helper function to test the permissions of a file.
-   *
-   * @param $filepath
-   *   String file path.
-   * @param $expected_mode
-   *   Octal integer like 0664 or 0777.
-   * @param $message
-   *   Optional message.
-   */
-  function assertFilePermissions($filepath, $expected_mode, $message = NULL) {
-    // Clear out PHP's file stat cache to be sure we see the current value.
-    clearstatcache();
-
-    // Mask out all but the last three octets.
-    $actual_mode = fileperms($filepath) & 0777;
-
-    // PHP on Windows has limited support for file permissions. Usually each of
-    // "user", "group" and "other" use one octal digit (3 bits) to represent the
-    // read/write/execute bits. On Windows, chmod() ignores the "group" and
-    // "other" bits, and fileperms() returns the "user" bits in all three
-    // positions. $expected_mode is updated to reflect this.
-    if (substr(PHP_OS, 0, 3) == 'WIN') {
-      // Reset the "group" and "other" bits.
-      $expected_mode = $expected_mode & 0700;
-      // Shift the "user" bits to the "group" and "other" positions also.
-      $expected_mode = $expected_mode | $expected_mode >> 3 | $expected_mode >> 6;
-    }
-
-    if (!isset($message)) {
-      $message = t('Expected file permission to be %expected, actually were %actual.', array('%actual' => decoct($actual_mode), '%expected' => decoct($expected_mode)));
-    }
-    $this->assertEqual($actual_mode, $expected_mode, $message);
-  }
-
-  /**
-   * Helper function to test the permissions of a directory.
-   *
-   * @param $directory
-   *   String directory path.
-   * @param $expected_mode
-   *   Octal integer like 0664 or 0777.
-   * @param $message
-   *   Optional message.
-   */
-  function assertDirectoryPermissions($directory, $expected_mode, $message = NULL) {
-    // Clear out PHP's file stat cache to be sure we see the current value.
-    clearstatcache();
-
-    // Mask out all but the last three octets.
-    $actual_mode = fileperms($directory) & 0777;
-
-    // PHP on Windows has limited support for file permissions. Usually each of
-    // "user", "group" and "other" use one octal digit (3 bits) to represent the
-    // read/write/execute bits. On Windows, chmod() ignores the "group" and
-    // "other" bits, and fileperms() returns the "user" bits in all three
-    // positions. $expected_mode is updated to reflect this.
-    if (substr(PHP_OS, 0, 3) == 'WIN') {
-      // Reset the "group" and "other" bits.
-      $expected_mode = $expected_mode & 0700;
-      // Shift the "user" bits to the "group" and "other" positions also.
-      $expected_mode = $expected_mode | $expected_mode >> 3 | $expected_mode >> 6;
-    }
-
-    if (!isset($message)) {
-      $message = t('Expected directory permission to be %expected, actually were %actual.', array('%actual' => decoct($actual_mode), '%expected' => decoct($expected_mode)));
-    }
-    $this->assertEqual($actual_mode, $expected_mode, $message);
-  }
-
-  /**
-   * Create a directory and assert it exists.
-   *
-   * @param $path
-   *   Optional string with a directory path. If none is provided, a random
-   *   name in the site's files directory will be used.
-   * @return
-   *   The path to the directory.
-   */
-  function createDirectory($path = NULL) {
-    // A directory to operate on.
-    if (!isset($path)) {
-      $path = file_default_scheme() . '://' . $this->randomName();
-    }
-    $this->assertTrue(drupal_mkdir($path) && is_dir($path), t('Directory was created successfully.'));
-    return $path;
-  }
-
-  /**
-   * Create a file and save it to the files table and assert that it occurs
-   * correctly.
-   *
-   * @param $filepath
-   *   Optional string specifying the file path. If none is provided then a
-   *   randomly named file will be created in the site's files directory.
-   * @param $contents
-   *   Optional contents to save into the file. If a NULL value is provided an
-   *   arbitrary string will be used.
-   * @param $scheme
-   *   Optional string indicating the stream scheme to use. Drupal core includes
-   *   public, private, and temporary. The public wrapper is the default.
-   * @return
-   *   File object.
-   */
-  function createFile($filepath = NULL, $contents = NULL, $scheme = NULL) {
-    if (!isset($filepath)) {
-      // Prefix with non-latin characters to ensure that all file-related
-      // tests work with international filenames.
-      $filepath = 'Файл для тестирования ' . $this->randomName();
-    }
-    if (!isset($scheme)) {
-      $scheme = file_default_scheme();
-    }
-    $filepath = $scheme . '://' . $filepath;
-
-    if (!isset($contents)) {
-      $contents = "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data.";
-    }
-
-    file_put_contents($filepath, $contents);
-    $this->assertTrue(is_file($filepath), t('The test file exists on the disk.'), 'Create test file');
-
-    $file = new stdClass();
-    $file->uri = $filepath;
-    $file->filename = drupal_basename($file->uri);
-    $file->filemime = 'text/plain';
-    $file->uid = 1;
-    $file->timestamp = REQUEST_TIME;
-    $file->filesize = filesize($file->uri);
-    $file->status = 0;
-    // Write the record directly rather than using the API so we don't invoke
-    // the hooks.
-    $this->assertNotIdentical(drupal_write_record('file_managed', $file), FALSE, t('The file was added to the database.'), 'Create test file');
-
-    return entity_create('file', (array) $file);
-  }
-}
-
-/**
- * Base class for file tests that use the file_test module to test uploads and
- * hooks.
- */
-class FileHookTestCase extends FileTestCase {
-  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.
-   * @param $message
-   *   Optional translated string message.
-   */
-  function assertFileHookCalled($hook, $expected_count = 1, $message = NULL) {
-    $actual_count = count(file_test_get_calls($hook));
-
-    if (!isset($message)) {
-      if ($actual_count == $expected_count) {
-        $message = t('hook_file_@name was called correctly.', array('@name' => $hook));
-      }
-      elseif ($expected_count == 0) {
-        $message = format_plural($actual_count, 'hook_file_@name was not expected to be called but was actually called once.', 'hook_file_@name was not expected to be called but was actually called @count times.', array('@name' => $hook, '@count' => $actual_count));
-      }
-      else {
-        $message = t('hook_file_@name was expected to be called %expected times but was called %actual times.', array('@name' => $hook, '%expected' => $expected_count, '%actual' => $actual_count));
-      }
-    }
-    $this->assertEqual($actual_count, $expected_count, $message);
-  }
-}
-
-
-/**
- *  This will run tests against the file_space_used() function.
- */
-class FileSpaceUsedTest extends FileTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'File space used tests',
-      'description' => 'Tests the file_space_used() function.',
-      'group' => 'File API',
-    );
-  }
-
-  function setUp() {
-    parent::setUp();
-
-    // Create records for a couple of users with different sizes.
-    $file = array('uid' => 2, 'uri' => 'public://example1.txt', 'filesize' => 50, 'status' => FILE_STATUS_PERMANENT);
-    drupal_write_record('file_managed', $file);
-    $file = array('uid' => 2, 'uri' => 'public://example2.txt', 'filesize' => 20, 'status' => FILE_STATUS_PERMANENT);
-    drupal_write_record('file_managed', $file);
-    $file = array('uid' => 3, 'uri' => 'public://example3.txt', 'filesize' => 100, 'status' => FILE_STATUS_PERMANENT);
-    drupal_write_record('file_managed', $file);
-    $file = array('uid' => 3, 'uri' => 'public://example4.txt', 'filesize' => 200, 'status' => FILE_STATUS_PERMANENT);
-    drupal_write_record('file_managed', $file);
-
-    // Now create some non-permanent files.
-    $file = array('uid' => 2, 'uri' => 'public://example5.txt', 'filesize' => 1, 'status' => 0);
-    drupal_write_record('file_managed', $file);
-    $file = array('uid' => 3, 'uri' => 'public://example6.txt', 'filesize' => 3, 'status' => 0);
-    drupal_write_record('file_managed', $file);
-  }
-
-  /**
-   * Test different users with the default status.
-   */
-  function testFileSpaceUsed() {
-    // Test different users with default status.
-    $this->assertEqual(file_space_used(2), 70);
-    $this->assertEqual(file_space_used(3), 300);
-    $this->assertEqual(file_space_used(), 370);
-
-    // Test the status fields
-    $this->assertEqual(file_space_used(NULL, 0), 4);
-    $this->assertEqual(file_space_used(NULL, FILE_STATUS_PERMANENT), 370);
-
-    // Test both the user and status.
-    $this->assertEqual(file_space_used(1, 0), 0);
-    $this->assertEqual(file_space_used(1, FILE_STATUS_PERMANENT), 0);
-    $this->assertEqual(file_space_used(2, 0), 1);
-    $this->assertEqual(file_space_used(2, FILE_STATUS_PERMANENT), 70);
-    $this->assertEqual(file_space_used(3, 0), 3);
-    $this->assertEqual(file_space_used(3, FILE_STATUS_PERMANENT), 300);
-  }
-}
-
-/**
- *  This will run tests against the file validation functions (file_validate_*).
- */
-class FileValidatorTest extends WebTestBase {
-  public static function getInfo() {
-    return array(
-      'name' => 'File validator tests',
-      'description' => 'Tests the functions used to validate uploaded files.',
-      'group' => 'File API',
-    );
-  }
-
-  function setUp() {
-    parent::setUp();
-
-    $this->image = entity_create('file', array());
-    $this->image->uri = 'core/misc/druplicon.png';
-    $this->image->filename = drupal_basename($this->image->uri);
-
-    $this->non_image = entity_create('file', array());
-    $this->non_image->uri = 'core/misc/jquery.js';
-    $this->non_image->filename = drupal_basename($this->non_image->uri);
-  }
-
-  /**
-   * Test the file_validate_extensions() function.
-   */
-  function testFileValidateExtensions() {
-    $file = entity_create('file', array('filename' => 'asdf.txt'));
-    $errors = file_validate_extensions($file, 'asdf txt pork');
-    $this->assertEqual(count($errors), 0, t('Valid extension accepted.'), 'File');
-
-    $file->filename = 'asdf.txt';
-    $errors = file_validate_extensions($file, 'exe png');
-    $this->assertEqual(count($errors), 1, t('Invalid extension blocked.'), 'File');
-  }
-
-  /**
-   *  This ensures a specific file is actually an image.
-   */
-  function testFileValidateIsImage() {
-    $this->assertTrue(file_exists($this->image->uri), t('The image being tested exists.'), 'File');
-    $errors = file_validate_is_image($this->image);
-    $this->assertEqual(count($errors), 0, t('No error reported for our image file.'), 'File');
-
-    $this->assertTrue(file_exists($this->non_image->uri), t('The non-image being tested exists.'), 'File');
-    $errors = file_validate_is_image($this->non_image);
-    $this->assertEqual(count($errors), 1, t('An error reported for our non-image file.'), 'File');
-  }
-
-  /**
-   *  This ensures the resolution of a specific file is within bounds.
-   *  The image will be resized if it's too large.
-   */
-  function testFileValidateImageResolution() {
-    // Non-images.
-    $errors = file_validate_image_resolution($this->non_image);
-    $this->assertEqual(count($errors), 0, t("Shouldn't get any errors for a non-image file."), 'File');
-    $errors = file_validate_image_resolution($this->non_image, '50x50', '100x100');
-    $this->assertEqual(count($errors), 0, t("Don't check the resolution on non files."), 'File');
-
-    // Minimum size.
-    $errors = file_validate_image_resolution($this->image);
-    $this->assertEqual(count($errors), 0, t('No errors for an image when there is no minimum or maximum resolution.'), 'File');
-    $errors = file_validate_image_resolution($this->image, 0, '200x1');
-    $this->assertEqual(count($errors), 1, t("Got an error for an image that wasn't wide enough."), 'File');
-    $errors = file_validate_image_resolution($this->image, 0, '1x200');
-    $this->assertEqual(count($errors), 1, t("Got an error for an image that wasn't tall enough."), 'File');
-    $errors = file_validate_image_resolution($this->image, 0, '200x200');
-    $this->assertEqual(count($errors), 1, t('Small images report an error.'), 'File');
-
-    // Maximum size.
-    if (image_get_toolkit()) {
-      // Copy the image so that the original doesn't get resized.
-      copy('core/misc/druplicon.png', 'temporary://druplicon.png');
-      $this->image->uri = 'temporary://druplicon.png';
-
-      $errors = file_validate_image_resolution($this->image, '10x5');
-      $this->assertEqual(count($errors), 0, t('No errors should be reported when an oversized image can be scaled down.'), 'File');
-
-      $info = image_get_info($this->image->uri);
-      $this->assertTrue($info['width'] <= 10, t('Image scaled to correct width.'), 'File');
-      $this->assertTrue($info['height'] <= 5, t('Image scaled to correct height.'), 'File');
-
-      drupal_unlink('temporary://druplicon.png');
-    }
-    else {
-      // TODO: should check that the error is returned if no toolkit is available.
-      $errors = file_validate_image_resolution($this->image, '5x10');
-      $this->assertEqual(count($errors), 1, t("Oversize images that can't be scaled get an error."), 'File');
-    }
-  }
-
-  /**
-   *  This will ensure the filename length is valid.
-   */
-  function testFileValidateNameLength() {
-    // Create a new file entity.
-    $file = entity_create('file', array());
-
-    // Add a filename with an allowed length and test it.
-    $file->filename = str_repeat('x', 240);
-    $this->assertEqual(strlen($file->filename), 240);
-    $errors = file_validate_name_length($file);
-    $this->assertEqual(count($errors), 0, t('No errors reported for 240 length filename.'), 'File');
-
-    // Add a filename with a length too long and test it.
-    $file->filename = str_repeat('x', 241);
-    $errors = file_validate_name_length($file);
-    $this->assertEqual(count($errors), 1, t('An error reported for 241 length filename.'), 'File');
-
-    // Add a filename with an empty string and test it.
-    $file->filename = '';
-    $errors = file_validate_name_length($file);
-    $this->assertEqual(count($errors), 1, t('An error reported for 0 length filename.'), 'File');
-  }
-
-
-  /**
-   * Test file_validate_size().
-   */
-  function testFileValidateSize() {
-    global $user;
-    $original_user = $user;
-    drupal_save_session(FALSE);
-
-    // Run these test as uid = 1.
-    $user = user_load(1);
-
-    $file = entity_create('file', array('filesize' => 999999));
-    $errors = file_validate_size($file, 1, 1);
-    $this->assertEqual(count($errors), 0, t('No size limits enforced on uid=1.'), 'File');
-
-    // Run these tests as a regular user.
-    $user = $this->drupalCreateUser();
-
-    // Create a file with a size of 1000 bytes, and quotas of only 1 byte.
-    $file = entity_create('file', array('filesize' => 1000));
-    $errors = file_validate_size($file, 0, 0);
-    $this->assertEqual(count($errors), 0, t('No limits means no errors.'), 'File');
-    $errors = file_validate_size($file, 1, 0);
-    $this->assertEqual(count($errors), 1, t('Error for the file being over the limit.'), 'File');
-    $errors = file_validate_size($file, 0, 1);
-    $this->assertEqual(count($errors), 1, t('Error for the user being over their limit.'), 'File');
-    $errors = file_validate_size($file, 1, 1);
-    $this->assertEqual(count($errors), 2, t('Errors for both the file and their limit.'), 'File');
-
-    $user = $original_user;
-    drupal_save_session(TRUE);
-  }
-}
-
-
-
-/**
- *  Tests the file_unmanaged_save_data() function.
- */
-class FileUnmanagedSaveDataTest extends FileTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'Unmanaged file save data',
-      'description' => 'Tests the unmanaged file save data function.',
-      'group' => 'File API',
-    );
-  }
-
-  /**
-   * Test the file_unmanaged_save_data() function.
-   */
-  function testFileSaveData() {
-    $contents = $this->randomName(8);
-
-    // No filename.
-    $filepath = file_unmanaged_save_data($contents);
-    $this->assertTrue($filepath, t('Unnamed file saved correctly.'));
-    $this->assertEqual(file_uri_scheme($filepath), file_default_scheme(), t("File was placed in Drupal's files directory."));
-    $this->assertEqual($contents, file_get_contents($filepath), t('Contents of the file are correct.'));
-
-    // Provide a filename.
-    $filepath = file_unmanaged_save_data($contents, 'public://asdf.txt', FILE_EXISTS_REPLACE);
-    $this->assertTrue($filepath, t('Unnamed file saved correctly.'));
-    $this->assertEqual('asdf.txt', drupal_basename($filepath), t('File was named correctly.'));
-    $this->assertEqual($contents, file_get_contents($filepath), t('Contents of the file are correct.'));
-    $this->assertFilePermissions($filepath, variable_get('file_chmod_file', 0664));
-  }
-}
-
-/**
- *  Tests the file_unmanaged_save_data() function on remote filesystems.
- */
-class RemoteFileUnmanagedSaveDataTest extends FileUnmanagedSaveDataTest {
-  public static function getInfo() {
-    $info = parent::getInfo();
-    $info['group'] = 'File API (remote)';
-    return $info;
-  }
-
-  function setUp() {
-    parent::setUp('file_test');
-    variable_set('file_default_scheme', 'dummy-remote');
-  }
-}
-
-/**
- * Test the file_save_upload() function.
- */
-class FileSaveUploadTest extends FileHookTestCase {
-  /**
-   * An image file path for uploading.
-   */
-  protected $image;
-
-  /**
-   * A PHP file path for upload security testing.
-   */
-  protected $phpfile;
-
-  /**
-   * The largest file id when the test starts.
-   */
-  protected $maxFidBefore;
-
-  public static function getInfo() {
-    return array(
-      'name' => 'File uploading',
-      'description' => 'Tests the file uploading functions.',
-      'group' => 'File API',
-    );
-  }
-
-  function setUp() {
-    parent::setUp();
-    $account = $this->drupalCreateUser(array('access content'));
-    $this->drupalLogin($account);
-
-    $image_files = $this->drupalGetTestFiles('image');
-    $this->image = entity_create('file', (array) current($image_files));
-
-    list(, $this->image_extension) = explode('.', $this->image->filename);
-    $this->assertTrue(is_file($this->image->uri), t("The image file we're going to upload exists."));
-
-    $this->phpfile = current($this->drupalGetTestFiles('php'));
-    $this->assertTrue(is_file($this->phpfile->uri), t("The PHP file we're going to upload exists."));
-
-    $this->maxFidBefore = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
-
-    // Upload with replace to guarantee there's something there.
-    $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
-      'files[file_test_upload]' => drupal_realpath($this->image->uri),
-    );
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
-
-    // Check that the correct hooks were called then clean out the hook
-    // counters.
-    $this->assertFileHooksCalled(array('validate', 'insert'));
-    file_test_reset();
-  }
-
-  /**
-   * Test the file_save_upload() function.
-   */
-  function testNormal() {
-    $max_fid_after = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
-    $this->assertTrue($max_fid_after > $this->maxFidBefore, t('A new file was created.'));
-    $file1 = file_load($max_fid_after);
-    $this->assertTrue($file1, t('Loaded the file.'));
-    // MIME type of the uploaded image may be either image/jpeg or image/png.
-    $this->assertEqual(substr($file1->filemime, 0, 5), 'image', 'A MIME type was set.');
-
-    // Reset the hook counters to get rid of the 'load' we just called.
-    file_test_reset();
-
-    // Upload a second file.
-    $max_fid_before = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
-    $image2 = current($this->drupalGetTestFiles('image'));
-    $edit = array('files[file_test_upload]' => drupal_realpath($image2->uri));
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertRaw(t('You WIN!'));
-    $max_fid_after = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'insert'));
-
-    $file2 = file_load($max_fid_after);
-    $this->assertTrue($file2);
-    // MIME type of the uploaded image may be either image/jpeg or image/png.
-    $this->assertEqual(substr($file2->filemime, 0, 5), 'image', 'A MIME type was set.');
-
-    // Load both files using file_load_multiple().
-    $files = file_load_multiple(array($file1->fid, $file2->fid));
-    $this->assertTrue(isset($files[$file1->fid]), t('File was loaded successfully'));
-    $this->assertTrue(isset($files[$file2->fid]), t('File was loaded successfully'));
-
-    // Upload a third file to a subdirectory.
-    $image3 = current($this->drupalGetTestFiles('image'));
-    $image3_realpath = drupal_realpath($image3->uri);
-    $dir = $this->randomName();
-    $edit = array(
-      'files[file_test_upload]' => $image3_realpath,
-      'file_subdir' => $dir,
-    );
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertRaw(t('You WIN!'));
-    $this->assertTrue(is_file('temporary://' . $dir . '/' . trim(drupal_basename($image3_realpath))));
-
-    // Check that file_load_multiple() with no arguments returns FALSE.
-    $this->assertFalse(file_load_multiple(), t('No files were loaded.'));
-  }
-
-  /**
-   * Test extension handling.
-   */
-  function testHandleExtension() {
-    // The file being tested is a .gif which is in the default safe list
-    // of extensions to allow when the extension validator isn't used. This is
-    // implicitly tested at the testNormal() test. Here we tell
-    // file_save_upload() to only allow ".foo".
-    $extensions = 'foo';
-    $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
-      'files[file_test_upload]' => drupal_realpath($this->image->uri),
-      'extensions' => $extensions,
-    );
-
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $message = t('Only files with the following extensions are allowed:') . ' <em class="placeholder">' . $extensions . '</em>';
-    $this->assertRaw($message, t('Can\'t upload a disallowed extension'));
-    $this->assertRaw(t('Epic upload FAIL!'), t('Found the failure message.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate'));
-
-    // Reset the hook counters.
-    file_test_reset();
-
-    $extensions = 'foo ' . $this->image_extension;
-    // Now tell file_save_upload() to allow the extension of our test image.
-    $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
-      'files[file_test_upload]' => drupal_realpath($this->image->uri),
-      'extensions' => $extensions,
-    );
-
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertNoRaw(t('Only files with the following extensions are allowed:'), t('Can upload an allowed extension.'));
-    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'load', 'update'));
-
-    // Reset the hook counters.
-    file_test_reset();
-
-    // Now tell file_save_upload() to allow any extension.
-    $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
-      'files[file_test_upload]' => drupal_realpath($this->image->uri),
-      'allow_all_extensions' => TRUE,
-    );
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertNoRaw(t('Only files with the following extensions are allowed:'), t('Can upload any extension.'));
-    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'load', 'update'));
-  }
-
-  /**
-   * Test dangerous file handling.
-   */
-  function testHandleDangerousFile() {
-    // Allow the .php extension and make sure it gets renamed to .txt for
-    // safety. Also check to make sure its MIME type was changed.
-    $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
-      'files[file_test_upload]' => drupal_realpath($this->phpfile->uri),
-      'is_image_file' => FALSE,
-      'extensions' => 'php',
-    );
-
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $message = t('For security reasons, your upload has been renamed to') . ' <em class="placeholder">' . $this->phpfile->filename . '.txt' . '</em>';
-    $this->assertRaw($message, t('Dangerous file was renamed.'));
-    $this->assertRaw(t('File MIME type is text/plain.'), t('Dangerous file\'s MIME type was changed.'));
-    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'insert'));
-
-    // Ensure dangerous files are not renamed when insecure uploads is TRUE.
-    // Turn on insecure uploads.
-    variable_set('allow_insecure_uploads', 1);
-    // Reset the hook counters.
-    file_test_reset();
-
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertNoRaw(t('For security reasons, your upload has been renamed'), t('Found no security message.'));
-    $this->assertRaw(t('File name is !filename', array('!filename' => $this->phpfile->filename)), t('Dangerous file was not renamed when insecure uploads is TRUE.'));
-    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'insert'));
-
-    // Turn off insecure uploads.
-    variable_set('allow_insecure_uploads', 0);
-  }
-
-  /**
-   * Test file munge handling.
-   */
-  function testHandleFileMunge() {
-    // Ensure insecure uploads are disabled for this test.
-    variable_set('allow_insecure_uploads', 0);
-    $this->image = file_move($this->image, $this->image->uri . '.foo.' . $this->image_extension);
-
-    // Reset the hook counters to get rid of the 'move' we just called.
-    file_test_reset();
-
-    $extensions = $this->image_extension;
-    $edit = array(
-      'files[file_test_upload]' => drupal_realpath($this->image->uri),
-      'extensions' => $extensions,
-    );
-
-    $munged_filename = $this->image->filename;
-    $munged_filename = substr($munged_filename, 0, strrpos($munged_filename, '.'));
-    $munged_filename .= '_.' . $this->image_extension;
-
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertRaw(t('For security reasons, your upload has been renamed'), t('Found security message.'));
-    $this->assertRaw(t('File name is !filename', array('!filename' => $munged_filename)), t('File was successfully munged.'));
-    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'insert'));
-
-    // Ensure we don't munge files if we're allowing any extension.
-    // Reset the hook counters.
-    file_test_reset();
-
-    $edit = array(
-      'files[file_test_upload]' => drupal_realpath($this->image->uri),
-      'allow_all_extensions' => TRUE,
-    );
-
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertNoRaw(t('For security reasons, your upload has been renamed'), t('Found no security message.'));
-    $this->assertRaw(t('File name is !filename', array('!filename' => $this->image->filename)), t('File was not munged when allowing any extension.'));
-    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'insert'));
-  }
-
-  /**
-   * Test renaming when uploading over a file that already exists.
-   */
-  function testExistingRename() {
-    $edit = array(
-      'file_test_replace' => FILE_EXISTS_RENAME,
-      'files[file_test_upload]' => drupal_realpath($this->image->uri)
-    );
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'insert'));
-  }
-
-  /**
-   * Test replacement when uploading over a file that already exists.
-   */
-  function testExistingReplace() {
-    $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
-      'files[file_test_upload]' => drupal_realpath($this->image->uri)
-    );
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'load', 'update'));
-  }
-
-  /**
-   * Test for failure when uploading over a file that already exists.
-   */
-  function testExistingError() {
-    $edit = array(
-      'file_test_replace' => FILE_EXISTS_ERROR,
-      'files[file_test_upload]' => drupal_realpath($this->image->uri)
-    );
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertRaw(t('Epic upload FAIL!'), t('Found the failure message.'));
-
-    // Check that the no hooks were called while failing.
-    $this->assertFileHooksCalled(array());
-  }
-
-  /**
-   * Test for no failures when not uploading a file.
-   */
-  function testNoUpload() {
-    $this->drupalPost('file-test/upload', array(), t('Submit'));
-    $this->assertNoRaw(t('Epic upload FAIL!'), t('Failure message not found.'));
-  }
-}
-
-/**
- * Test the file_save_upload() function on remote filesystems.
- */
-class RemoteFileSaveUploadTest extends FileSaveUploadTest {
-  public static function getInfo() {
-    $info = parent::getInfo();
-    $info['group'] = 'File API (remote)';
-    return $info;
-  }
-
-  function setUp() {
-    parent::setUp('file_test');
-    variable_set('file_default_scheme', 'dummy-remote');
-  }
-}
-
-/**
- * Directory related tests.
- */
-class FileDirectoryTest extends FileTestCase {
-  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."));
-  }
-}
-
-/**
- * Directory related tests.
- */
-class RemoteFileDirectoryTest extends FileDirectoryTest {
-  public static function getInfo() {
-    $info = parent::getInfo();
-    $info['group'] = 'File API (remote)';
-    return $info;
-  }
-
-  function setUp() {
-    parent::setUp('file_test');
-    variable_set('file_default_scheme', 'dummy-remote');
-  }
-}
-
-/**
- * Tests the file_scan_directory() function.
- */
-class FileScanDirectoryTest extends FileTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'File scan directory',
-      'description' => 'Tests the file_scan_directory() function.',
-      'group' => 'File API',
-    );
-  }
-
-  function setUp() {
-    parent::setUp();
-    $this->path = drupal_get_path('module', 'simpletest') . '/files';
-  }
-
-  /**
-   * Check the format of the returned values.
-   */
-  function testReturn() {
-    // Grab a listing of all the JavaSscript files and check that they're
-    // passed to the callback.
-    $all_files = file_scan_directory($this->path, '/^javascript-/');
-    ksort($all_files);
-    $this->assertEqual(2, count($all_files), t('Found two, expected javascript files.'));
-
-    // Check the first file.
-    $file = reset($all_files);
-    $this->assertEqual(key($all_files), $file->uri, t('Correct array key was used for the first returned file.'));
-    $this->assertEqual($file->uri, $this->path . '/javascript-1.txt', t('First file name was set correctly.'));
-    $this->assertEqual($file->filename, 'javascript-1.txt', t('First basename was set correctly'));
-    $this->assertEqual($file->name, 'javascript-1', t('First name was set correctly.'));
-
-    // Check the second file.
-    $file = next($all_files);
-    $this->assertEqual(key($all_files), $file->uri, t('Correct array key was used for the second returned file.'));
-    $this->assertEqual($file->uri, $this->path . '/javascript-2.script', t('Second file name was set correctly.'));
-    $this->assertEqual($file->filename, 'javascript-2.script', t('Second basename was set correctly'));
-    $this->assertEqual($file->name, 'javascript-2', t('Second name was set correctly.'));
-  }
-
-  /**
-   * Check that the callback function is called correctly.
-   */
-  function testOptionCallback() {
-    // When nothing is matched nothing should be passed to the callback.
-    $all_files = file_scan_directory($this->path, '/^NONEXISTINGFILENAME/', array('callback' => 'file_test_file_scan_callback'));
-    $this->assertEqual(0, count($all_files), t('No files were found.'));
-    $results = file_test_file_scan_callback();
-    file_test_file_scan_callback_reset();
-    $this->assertEqual(0, count($results), t('No files were passed to the callback.'));
-
-    // Grab a listing of all the JavaSscript files and check that they're
-    // passed to the callback.
-    $all_files = file_scan_directory($this->path, '/^javascript-/', array('callback' => 'file_test_file_scan_callback'));
-    $this->assertEqual(2, count($all_files), t('Found two, expected javascript files.'));
-    $results = file_test_file_scan_callback();
-    file_test_file_scan_callback_reset();
-    $this->assertEqual(2, count($results), t('Files were passed to the callback.'));
-  }
-
-  /**
-   * Check that the no-mask parameter is honored.
-   */
-  function testOptionNoMask() {
-    // Grab a listing of all the JavaSscript files.
-    $all_files = file_scan_directory($this->path, '/^javascript-/');
-    $this->assertEqual(2, count($all_files), t('Found two, expected javascript files.'));
-
-    // Now use the nomast parameter to filter out the .script file.
-    $filtered_files = file_scan_directory($this->path, '/^javascript-/', array('nomask' => '/.script$/'));
-    $this->assertEqual(1, count($filtered_files), t('Filtered correctly.'));
-  }
-
-  /**
-   * Check that key parameter sets the return value's key.
-   */
-  function testOptionKey() {
-    // "filename", for the path starting with $dir.
-    $expected = array($this->path . '/javascript-1.txt', $this->path . '/javascript-2.script');
-    $actual = array_keys(file_scan_directory($this->path, '/^javascript-/', array('key' => 'filepath')));
-    sort($actual);
-    $this->assertEqual($expected, $actual, t('Returned the correct values for the filename key.'));
-
-    // "basename", for the basename of the file.
-    $expected = array('javascript-1.txt', 'javascript-2.script');
-    $actual = array_keys(file_scan_directory($this->path, '/^javascript-/', array('key' => 'filename')));
-    sort($actual);
-    $this->assertEqual($expected, $actual, t('Returned the correct values for the basename key.'));
-
-    // "name" for the name of the file without an extension.
-    $expected = array('javascript-1', 'javascript-2');
-    $actual = array_keys(file_scan_directory($this->path, '/^javascript-/', array('key' => 'name')));
-    sort($actual);
-    $this->assertEqual($expected, $actual, t('Returned the correct values for the name key.'));
-
-    // Invalid option that should default back to "filename".
-    $expected = array($this->path . '/javascript-1.txt', $this->path . '/javascript-2.script');
-    $actual = array_keys(file_scan_directory($this->path, '/^javascript-/', array('key' => 'INVALID')));
-    sort($actual);
-    $this->assertEqual($expected, $actual, t('An invalid key defaulted back to the default.'));
-  }
-
-  /**
-   * Check that the recurse option decends into subdirectories.
-   */
-  function testOptionRecurse() {
-    $files = file_scan_directory(drupal_get_path('module', 'simpletest'), '/^javascript-/', array('recurse' => FALSE));
-    $this->assertTrue(empty($files), t("Without recursion couldn't find javascript files."));
-
-    $files = file_scan_directory(drupal_get_path('module', 'simpletest'), '/^javascript-/', array('recurse' => TRUE));
-    $this->assertEqual(2, count($files), t('With recursion we found the expected javascript files.'));
-  }
-
-
-  /**
-   * Check that the min_depth options lets us ignore files in the starting
-   * directory.
-   */
-  function testOptionMinDepth() {
-    $files = file_scan_directory($this->path, '/^javascript-/', array('min_depth' => 0));
-    $this->assertEqual(2, count($files), t('No minimum-depth gets files in current directory.'));
-
-    $files = file_scan_directory($this->path, '/^javascript-/', array('min_depth' => 1));
-    $this->assertTrue(empty($files), t("Minimum-depth of 1 successfully excludes files from current directory."));
-  }
-}
-
-/**
- * Tests the file_scan_directory() function on remote filesystems.
- */
-class RemoteFileScanDirectoryTest extends FileScanDirectoryTest {
-  public static function getInfo() {
-    $info = parent::getInfo();
-    $info['group'] = 'File API (remote)';
-    return $info;
-  }
-
-  function setUp() {
-    parent::setUp('file_test');
-    variable_set('file_default_scheme', 'dummy-remote');
-  }
-}
-
-/**
- * Deletion related tests.
- */
-class FileUnmanagedDeleteTest extends FileTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'Unmanaged file delete',
-      'description' => 'Tests the unmanaged file delete function.',
-      'group' => 'File API',
-    );
-  }
-
-  /**
-   * Delete a normal file.
-   */
-  function testNormal() {
-    // Create a file for testing
-    $file = $this->createFile();
-
-    // Delete a regular file
-    $this->assertTrue(file_unmanaged_delete($file->uri), t('Deleted worked.'));
-    $this->assertFalse(file_exists($file->uri), t('Test file has actually been deleted.'));
-  }
-
-  /**
-   * Try deleting a missing file.
-   */
-  function testMissing() {
-    // Try to delete a non-existing file
-    $this->assertTrue(file_unmanaged_delete(file_default_scheme() . '/' . $this->randomName()), t('Returns true when deleting a non-existent file.'));
-  }
-
-  /**
-   * Try deleting a directory.
-   */
-  function testDirectory() {
-    // A directory to operate on.
-    $directory = $this->createDirectory();
-
-    // Try to delete a directory
-    $this->assertFalse(file_unmanaged_delete($directory), t('Could not delete the delete directory.'));
-    $this->assertTrue(file_exists($directory), t('Directory has not been deleted.'));
-  }
-}
-
-/**
- * Deletion related tests on remote filesystems.
- */
-class RemoteFileUnmanagedDeleteTest extends FileUnmanagedDeleteTest {
-  public static function getInfo() {
-    $info = parent::getInfo();
-    $info['group'] = 'File API (remote)';
-    return $info;
-  }
-
-  function setUp() {
-    parent::setUp('file_test');
-    variable_set('file_default_scheme', 'dummy-remote');
-  }
-}
-
-/**
- * Deletion related tests.
- */
-class FileUnmanagedDeleteRecursiveTest extends FileTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'Unmanaged recursive file delete',
-      'description' => 'Tests the unmanaged file delete recursive function.',
-      'group' => 'File API',
-    );
-  }
-
-  /**
-   * Delete a normal file.
-   */
-  function testSingleFile() {
-    // Create a file for testing
-    $filepath = file_default_scheme() . '://' . $this->randomName();
-    file_put_contents($filepath, '');
-
-    // Delete the file.
-    $this->assertTrue(file_unmanaged_delete_recursive($filepath), t('Function reported success.'));
-    $this->assertFalse(file_exists($filepath), t('Test file has been deleted.'));
-  }
-
-  /**
-   * Try deleting an empty directory.
-   */
-  function testEmptyDirectory() {
-    // A directory to operate on.
-    $directory = $this->createDirectory();
-
-    // Delete the directory.
-    $this->assertTrue(file_unmanaged_delete_recursive($directory), t('Function reported success.'));
-    $this->assertFalse(file_exists($directory), t('Directory has been deleted.'));
-  }
-
-  /**
-   * Try deleting a directory with some files.
-   */
-  function testDirectory() {
-    // A directory to operate on.
-    $directory = $this->createDirectory();
-    $filepathA = $directory . '/A';
-    $filepathB = $directory . '/B';
-    file_put_contents($filepathA, '');
-    file_put_contents($filepathB, '');
-
-    // Delete the directory.
-    $this->assertTrue(file_unmanaged_delete_recursive($directory), t('Function reported success.'));
-    $this->assertFalse(file_exists($filepathA), t('Test file A has been deleted.'));
-    $this->assertFalse(file_exists($filepathB), t('Test file B has been deleted.'));
-    $this->assertFalse(file_exists($directory), t('Directory has been deleted.'));
-  }
-
-  /**
-   * Try deleting subdirectories with some files.
-   */
-  function testSubDirectory() {
-    // A directory to operate on.
-    $directory = $this->createDirectory();
-    $subdirectory = $this->createDirectory($directory . '/sub');
-    $filepathA = $directory . '/A';
-    $filepathB = $subdirectory . '/B';
-    file_put_contents($filepathA, '');
-    file_put_contents($filepathB, '');
-
-    // Delete the directory.
-    $this->assertTrue(file_unmanaged_delete_recursive($directory), t('Function reported success.'));
-    $this->assertFalse(file_exists($filepathA), t('Test file A has been deleted.'));
-    $this->assertFalse(file_exists($filepathB), t('Test file B has been deleted.'));
-    $this->assertFalse(file_exists($subdirectory), t('Subdirectory has been deleted.'));
-    $this->assertFalse(file_exists($directory), t('Directory has been deleted.'));
-  }
-}
-
-/**
- * Deletion related tests on remote filesystems.
- */
-class RemoteFileUnmanagedDeleteRecursiveTest extends FileUnmanagedDeleteRecursiveTest {
-  public static function getInfo() {
-    $info = parent::getInfo();
-    $info['group'] = 'File API (remote)';
-    return $info;
-  }
-
-  function setUp() {
-    parent::setUp('file_test');
-    variable_set('file_default_scheme', 'dummy-remote');
-  }
-}
-
-/**
- * Unmanaged move related tests.
- */
-class FileUnmanagedMoveTest extends FileTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'Unmanaged file moving',
-      'description' => 'Tests the unmanaged file move function.',
-      'group' => 'File API',
-    );
-  }
-
-  /**
-   * Move a normal file.
-   */
-  function testNormal() {
-    // Create a file for testing
-    $file = $this->createFile();
-
-    // Moving to a new name.
-    $desired_filepath = 'public://' . $this->randomName();
-    $new_filepath = file_unmanaged_move($file->uri, $desired_filepath, FILE_EXISTS_ERROR);
-    $this->assertTrue($new_filepath, t('Move was successful.'));
-    $this->assertEqual($new_filepath, $desired_filepath, t('Returned expected filepath.'));
-    $this->assertTrue(file_exists($new_filepath), t('File exists at the new location.'));
-    $this->assertFalse(file_exists($file->uri), t('No file remains at the old location.'));
-    $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
-
-    // Moving with rename.
-    $desired_filepath = 'public://' . $this->randomName();
-    $this->assertTrue(file_exists($new_filepath), t('File exists before moving.'));
-    $this->assertTrue(file_put_contents($desired_filepath, ' '), t('Created a file so a rename will have to happen.'));
-    $newer_filepath = file_unmanaged_move($new_filepath, $desired_filepath, FILE_EXISTS_RENAME);
-    $this->assertTrue($newer_filepath, t('Move was successful.'));
-    $this->assertNotEqual($newer_filepath, $desired_filepath, t('Returned expected filepath.'));
-    $this->assertTrue(file_exists($newer_filepath), t('File exists at the new location.'));
-    $this->assertFalse(file_exists($new_filepath), t('No file remains at the old location.'));
-    $this->assertFilePermissions($newer_filepath, variable_get('file_chmod_file', 0664));
-
-    // TODO: test moving to a directory (rather than full directory/file path)
-    // TODO: test creating and moving normal files (rather than streams)
-  }
-
-  /**
-   * Try to move a missing file.
-   */
-  function testMissing() {
-    // Move non-existent file.
-    $new_filepath = file_unmanaged_move($this->randomName(), $this->randomName());
-    $this->assertFalse($new_filepath, t('Moving a missing file fails.'));
-  }
-
-  /**
-   * Try to move a file onto itself.
-   */
-  function testOverwriteSelf() {
-    // Create a file for testing.
-    $file = $this->createFile();
-
-    // Move the file onto itself without renaming shouldn't make changes.
-    $new_filepath = file_unmanaged_move($file->uri, $file->uri, FILE_EXISTS_REPLACE);
-    $this->assertFalse($new_filepath, t('Moving onto itself without renaming fails.'));
-    $this->assertTrue(file_exists($file->uri), t('File exists after moving onto itself.'));
-
-    // Move the file onto itself with renaming will result in a new filename.
-    $new_filepath = file_unmanaged_move($file->uri, $file->uri, FILE_EXISTS_RENAME);
-    $this->assertTrue($new_filepath, t('Moving onto itself with renaming works.'));
-    $this->assertFalse(file_exists($file->uri), t('Original file has been removed.'));
-    $this->assertTrue(file_exists($new_filepath), t('File exists after moving onto itself.'));
-  }
-}
-
-/**
- * Unmanaged move related tests on remote filesystems.
- */
-class RemoteFileUnmanagedMoveTest extends FileUnmanagedMoveTest {
-  public static function getInfo() {
-    $info = parent::getInfo();
-    $info['group'] = 'File API (remote)';
-    return $info;
-  }
-
-  function setUp() {
-    parent::setUp('file_test');
-    variable_set('file_default_scheme', 'dummy-remote');
-  }
-}
-
-/**
- * Unmanaged copy related tests.
- */
-class FileUnmanagedCopyTest extends FileTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'Unmanaged file copying',
-      'description' => 'Tests the unmanaged file copy function.',
-      'group' => 'File API',
-    );
-  }
-
-  /**
-   * Copy a normal file.
-   */
-  function testNormal() {
-    // Create a file for testing
-    $file = $this->createFile();
-
-    // Copying to a new name.
-    $desired_filepath = 'public://' . $this->randomName();
-    $new_filepath = file_unmanaged_copy($file->uri, $desired_filepath, FILE_EXISTS_ERROR);
-    $this->assertTrue($new_filepath, t('Copy was successful.'));
-    $this->assertEqual($new_filepath, $desired_filepath, t('Returned expected filepath.'));
-    $this->assertTrue(file_exists($file->uri), t('Original file remains.'));
-    $this->assertTrue(file_exists($new_filepath), t('New file exists.'));
-    $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
-
-    // Copying with rename.
-    $desired_filepath = 'public://' . $this->randomName();
-    $this->assertTrue(file_put_contents($desired_filepath, ' '), t('Created a file so a rename will have to happen.'));
-    $newer_filepath = file_unmanaged_copy($file->uri, $desired_filepath, FILE_EXISTS_RENAME);
-    $this->assertTrue($newer_filepath, t('Copy was successful.'));
-    $this->assertNotEqual($newer_filepath, $desired_filepath, t('Returned expected filepath.'));
-    $this->assertTrue(file_exists($file->uri), t('Original file remains.'));
-    $this->assertTrue(file_exists($newer_filepath), t('New file exists.'));
-    $this->assertFilePermissions($newer_filepath, variable_get('file_chmod_file', 0664));
-
-    // TODO: test copying to a directory (rather than full directory/file path)
-    // TODO: test copying normal files using normal paths (rather than only streams)
-  }
-
-  /**
-   * Copy a non-existent file.
-   */
-  function testNonExistent() {
-    // Copy non-existent file
-    $desired_filepath = $this->randomName();
-    $this->assertFalse(file_exists($desired_filepath), t("Randomly named file doesn't exists."));
-    $new_filepath = file_unmanaged_copy($desired_filepath, $this->randomName());
-    $this->assertFalse($new_filepath, t('Copying a missing file fails.'));
-  }
-
-  /**
-   * Copy a file onto itself.
-   */
-  function testOverwriteSelf() {
-    // Create a file for testing
-    $file = $this->createFile();
-
-    // Copy the file onto itself with renaming works.
-    $new_filepath = file_unmanaged_copy($file->uri, $file->uri, FILE_EXISTS_RENAME);
-    $this->assertTrue($new_filepath, t('Copying onto itself with renaming works.'));
-    $this->assertNotEqual($new_filepath, $file->uri, t('Copied file has a new name.'));
-    $this->assertTrue(file_exists($file->uri), t('Original file exists after copying onto itself.'));
-    $this->assertTrue(file_exists($new_filepath), t('Copied file exists after copying onto itself.'));
-    $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
-
-    // Copy the file onto itself without renaming fails.
-    $new_filepath = file_unmanaged_copy($file->uri, $file->uri, FILE_EXISTS_ERROR);
-    $this->assertFalse($new_filepath, t('Copying onto itself without renaming fails.'));
-    $this->assertTrue(file_exists($file->uri), t('File exists after copying onto itself.'));
-
-    // Copy the file into same directory without renaming fails.
-    $new_filepath = file_unmanaged_copy($file->uri, drupal_dirname($file->uri), FILE_EXISTS_ERROR);
-    $this->assertFalse($new_filepath, t('Copying onto itself fails.'));
-    $this->assertTrue(file_exists($file->uri), t('File exists after copying onto itself.'));
-
-    // Copy the file into same directory with renaming works.
-    $new_filepath = file_unmanaged_copy($file->uri, drupal_dirname($file->uri), FILE_EXISTS_RENAME);
-    $this->assertTrue($new_filepath, t('Copying into same directory works.'));
-    $this->assertNotEqual($new_filepath, $file->uri, t('Copied file has a new name.'));
-    $this->assertTrue(file_exists($file->uri), t('Original file exists after copying onto itself.'));
-    $this->assertTrue(file_exists($new_filepath), t('Copied file exists after copying onto itself.'));
-    $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
-  }
-}
-
-/**
- * Unmanaged copy related tests on remote filesystems.
- */
-class RemoteFileUnmanagedCopyTest extends FileUnmanagedCopyTest {
-  public static function getInfo() {
-    $info = parent::getInfo();
-    $info['group'] = 'File API (remote)';
-    return $info;
-  }
-
-  function setUp() {
-    parent::setUp('file_test');
-    variable_set('file_default_scheme', 'dummy-remote');
-  }
-}
-
-/**
- * Deletion related tests.
- */
-class FileDeleteTest extends FileHookTestCase {
-  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.'));
-  }
-}
-
-
-/**
- * Move related tests
- */
-class FileMoveTest extends FileHookTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'File moving',
-      'description' => 'Tests the file move function.',
-      'group' => 'File API',
-    );
-  }
-
-  /**
-   * Move a normal file.
-   */
-  function testNormal() {
-    $contents = $this->randomName(10);
-    $source = $this->createFile(NULL, $contents);
-    $desired_filepath = 'public://' . $this->randomName();
-
-    // Clone the object so we don't have to worry about the function changing
-    // our reference copy.
-    $result = file_move(clone $source, $desired_filepath, FILE_EXISTS_ERROR);
-
-    // Check the return status and that the contents changed.
-    $this->assertTrue($result, t('File moved successfully.'));
-    $this->assertFalse(file_exists($source->uri));
-    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file correctly written.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('move', 'load', 'update'));
-
-    // Make sure we got the same file back.
-    $this->assertEqual($source->fid, $result->fid, t("Source file id's' %fid is unchanged after move.", array('%fid' => $source->fid)));
-
-    // Reload the file from the database and check that the changes were
-    // actually saved.
-    $loaded_file = file_load($result->fid, TRUE);
-    $this->assertTrue($loaded_file, t('File can be loaded from the database.'));
-    $this->assertFileUnchanged($result, $loaded_file);
-  }
-
-  /**
-   * Test renaming when moving onto 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_move(clone $source, $target->uri, FILE_EXISTS_RENAME);
-
-    // Check the return status and that the contents changed.
-    $this->assertTrue($result, t('File moved successfully.'));
-    $this->assertFalse(file_exists($source->uri));
-    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file correctly written.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('move', 'load', 'update'));
-
-    // Compare the returned value to what made it into the database.
-    $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
-    // The target file should not have been altered.
-    $this->assertFileUnchanged($target, file_load($target->fid, TRUE));
-    // Make sure we end up with two distinct files afterwards.
-    $this->assertDifferentFile($target, $result);
-
-    // Compare the source and results.
-    $loaded_source = file_load($source->fid, TRUE);
-    $this->assertEqual($loaded_source->fid, $result->fid, t("Returned file's id matches the source."));
-    $this->assertNotEqual($loaded_source->uri, $source->uri, t("Returned file path has changed from the original."));
-  }
-
-  /**
-   * Test replacement when moving onto 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_move(clone $source, $target->uri, FILE_EXISTS_REPLACE);
-
-    // Look at the results.
-    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were overwritten.'));
-    $this->assertFalse(file_exists($source->uri));
-    $this->assertTrue($result, t('File moved successfully.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('move', 'update', 'delete', 'load'));
-
-    // Reload the file from the database and check that the changes were
-    // actually saved.
-    $loaded_result = file_load($result->fid, TRUE);
-    $this->assertFileUnchanged($result, $loaded_result);
-    // Check that target was re-used.
-    $this->assertSameFile($target, $loaded_result);
-    // Source and result should be totally different.
-    $this->assertDifferentFile($source, $loaded_result);
-  }
-
-  /**
-   * Test replacement when moving onto itself.
-   */
-  function testExistingReplaceSelf() {
-    // Setup a file to overwrite.
-    $contents = $this->randomName(10);
-    $source = $this->createFile(NULL, $contents);
-
-    // Copy the file over itself. Clone the object so we don't have to worry
-    // about the function changing our reference copy.
-    $result = file_move(clone $source, $source->uri, FILE_EXISTS_REPLACE);
-    $this->assertFalse($result, t('File move failed.'));
-    $this->assertEqual($contents, file_get_contents($source->uri), t('Contents of file were not altered.'));
-
-    // Check that no hooks were called while failing.
-    $this->assertFileHooksCalled(array());
-
-    // Load the file from the database and make sure it is identical to what
-    // was returned.
-    $this->assertFileUnchanged($source, file_load($source->fid, TRUE));
-  }
-
-  /**
-   * Test that moving onto 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_move(clone $source, $target->uri, FILE_EXISTS_ERROR);
-
-    // Check the return status and that the contents did not change.
-    $this->assertFalse($result, t('File move failed.'));
-    $this->assertTrue(file_exists($source->uri));
-    $this->assertEqual($contents, file_get_contents($target->uri), t('Contents of file were not altered.'));
-
-    // Check that no hooks were called while failing.
-    $this->assertFileHooksCalled(array());
-
-    // Load the file from the database and make sure it is identical to what
-    // was returned.
-    $this->assertFileUnchanged($source, file_load($source->fid, TRUE));
-    $this->assertFileUnchanged($target, file_load($target->fid, TRUE));
-  }
-}
-
-
-/**
- * Copy related tests.
- */
-class FileCopyTest extends FileHookTestCase {
-  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));
-  }
-}
-
-
-/**
- * Tests the file_load() function.
- */
-class FileLoadTest extends FileHookTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'File loading',
-      'description' => 'Tests the file_load() function.',
-      'group' => 'File API',
-    );
-  }
-
-  /**
-   * Try to load a non-existent file by fid.
-   */
-  function testLoadMissingFid() {
-    $this->assertFalse(file_load(-1), t("Try to load an invalid fid fails."));
-    $this->assertFileHooksCalled(array());
-  }
-
-  /**
-   * Try to load a non-existent file by URI.
-   */
-  function testLoadMissingFilepath() {
-    $files = file_load_multiple(array(), array('uri' => 'foobar://misc/druplicon.png'));
-    $this->assertFalse(reset($files), t("Try to load a file that doesn't exist in the database fails."));
-    $this->assertFileHooksCalled(array());
-  }
-
-  /**
-   * Try to load a non-existent file by status.
-   */
-  function testLoadInvalidStatus() {
-    $files = file_load_multiple(array(), array('status' => -99));
-    $this->assertFalse(reset($files), t("Trying to load a file with an invalid status fails."));
-    $this->assertFileHooksCalled(array());
-  }
-
-  /**
-   * Load a single file and ensure that the correct values are returned.
-   */
-  function testSingleValues() {
-    // Create a new file entity from scratch so we know the values.
-    $file = $this->createFile('druplicon.txt', NULL, 'public');
-
-    $by_fid_file = file_load($file->fid);
-    $this->assertFileHookCalled('load');
-    $this->assertTrue(is_object($by_fid_file), t('file_load() returned an object.'));
-    $this->assertEqual($by_fid_file->fid, $file->fid, t("Loading by fid got the same fid."), 'File');
-    $this->assertEqual($by_fid_file->uri, $file->uri, t("Loading by fid got the correct filepath."), 'File');
-    $this->assertEqual($by_fid_file->filename, $file->filename, t("Loading by fid got the correct filename."), 'File');
-    $this->assertEqual($by_fid_file->filemime, $file->filemime, t("Loading by fid got the correct MIME type."), 'File');
-    $this->assertEqual($by_fid_file->status, $file->status, t("Loading by fid got the correct status."), 'File');
-    $this->assertTrue($by_fid_file->file_test['loaded'], t('file_test_file_load() was able to modify the file during load.'));
-  }
-
-  /**
-   * This will test loading file data from the database.
-   */
-  function testMultiple() {
-    // Create a new file entity.
-    $file = $this->createFile('druplicon.txt', NULL, 'public');
-
-    // Load by path.
-    file_test_reset();
-    $by_path_files = file_load_multiple(array(), array('uri' => $file->uri));
-    $this->assertFileHookCalled('load');
-    $this->assertEqual(1, count($by_path_files), t('file_load_multiple() returned an array of the correct size.'));
-    $by_path_file = reset($by_path_files);
-    $this->assertTrue($by_path_file->file_test['loaded'], t('file_test_file_load() was able to modify the file during load.'));
-    $this->assertEqual($by_path_file->fid, $file->fid, t("Loading by filepath got the correct fid."), 'File');
-
-    // Load by fid.
-    file_test_reset();
-    $by_fid_files = file_load_multiple(array($file->fid), array());
-    $this->assertFileHookCalled('load');
-    $this->assertEqual(1, count($by_fid_files), t('file_load_multiple() returned an array of the correct size.'));
-    $by_fid_file = reset($by_fid_files);
-    $this->assertTrue($by_fid_file->file_test['loaded'], t('file_test_file_load() was able to modify the file during load.'));
-    $this->assertEqual($by_fid_file->uri, $file->uri, t("Loading by fid got the correct filepath."), 'File');
-  }
-}
-
-/**
- * Tests saving files.
- */
-class FileSaveTest extends FileHookTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'File saving',
-      'description' => 'File saving tests',
-      'group' => 'File API',
-    );
-  }
-
-  function testFileSave() {
-    // Create a new file entity.
-    $file = entity_create('file', array(
-      'uid' => 1,
-      'filename' => 'druplicon.txt',
-      'uri' => 'public://druplicon.txt',
-      'filemime' => 'text/plain',
-      'timestamp' => 1,
-      'status' => FILE_STATUS_PERMANENT,
-    ));
-    file_put_contents($file->uri, 'hello world');
-
-    // Save it, inserting a new record.
-    $file->save();
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('insert'));
-
-    $this->assertTrue($file->fid > 0, t("A new file ID is set when saving a new file to the database."), 'File');
-    $loaded_file = db_query('SELECT * FROM {file_managed} f WHERE f.fid = :fid', array(':fid' => $file->fid))->fetchObject();
-    $this->assertNotNull($loaded_file, t("Record exists in the database."));
-    $this->assertEqual($loaded_file->status, $file->status, t("Status was saved correctly."));
-    $this->assertEqual($file->filesize, filesize($file->uri), t("File size was set correctly."), 'File');
-    $this->assertTrue($file->timestamp > 1, t("File size was set correctly."), 'File');
-    $this->assertEqual($loaded_file->langcode, LANGUAGE_NOT_SPECIFIED, t("Langcode was defaulted correctly."));
-
-    // Resave the file, updating the existing record.
-    file_test_reset();
-    $file->status = 7;
-    $file->langcode = 'en';
-    $file->save();
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('load', 'update'));
-
-    $this->assertEqual($file->fid, $file->fid, t("The file ID of an existing file is not changed when updating the database."), 'File');
-    $this->assertTrue($file->timestamp >= $file->timestamp, t("Timestamp didn't go backwards."), 'File');
-    $loaded_file = db_query('SELECT * FROM {file_managed} f WHERE f.fid = :fid', array(':fid' => $file->fid))->fetchObject();
-    $this->assertNotNull($loaded_file, t("Record still exists in the database."), 'File');
-    $this->assertEqual($loaded_file->status, $file->status, t("Status was saved correctly."));
-    $this->assertEqual($loaded_file->langcode, 'en', t("Langcode was saved correctly."));
-
-    // Try to insert a second file with the same name apart from case insensitivity
-    // to ensure the 'uri' index allows for filenames with different cases.
-    $file = entity_create('file', array(
-      'uid' => 1,
-      'filename' => 'DRUPLICON.txt',
-      'uri' => 'public://DRUPLICON.txt',
-      'filemime' => 'text/plain',
-      'timestamp' => 1,
-      'status' => FILE_STATUS_PERMANENT,
-    ));
-    file_put_contents($file->uri, 'hello world');
-    $file->save();
-  }
-}
-
-/**
- * Tests file usage functions.
- */
-class FileUsageTest extends FileTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'File usage',
-      'description' => 'Tests the file usage functions.',
-      'group' => 'File',
-    );
-  }
-
-  /**
-   * Tests file_usage_list().
-   */
-  function testGetUsage() {
-    $file = $this->createFile();
-    db_insert('file_usage')
-      ->fields(array(
-        'fid' => $file->fid,
-        'module' => 'testing',
-        'type' => 'foo',
-        'id' => 1,
-        'count' => 1
-      ))
-      ->execute();
-    db_insert('file_usage')
-      ->fields(array(
-        'fid' => $file->fid,
-        'module' => 'testing',
-        'type' => 'bar',
-        'id' => 2,
-        'count' => 2
-      ))
-      ->execute();
-
-    $usage = file_usage_list($file);
-
-    $this->assertEqual(count($usage['testing']), 2, t('Returned the correct number of items.'));
-    $this->assertTrue(isset($usage['testing']['foo'][1]), t('Returned the correct id.'));
-    $this->assertTrue(isset($usage['testing']['bar'][2]), t('Returned the correct id.'));
-    $this->assertEqual($usage['testing']['foo'][1], 1, t('Returned the correct count.'));
-    $this->assertEqual($usage['testing']['bar'][2], 2, t('Returned the correct count.'));
-  }
-
-  /**
-   * Tests file_usage_add().
-   */
-  function testAddUsage() {
-    $file = $this->createFile();
-    file_usage_add($file, 'testing', 'foo', 1);
-    // Add the file twice to ensure that the count is incremented rather than
-    // creating additional records.
-    file_usage_add($file, 'testing', 'bar', 2);
-    file_usage_add($file, 'testing', 'bar', 2);
-
-    $usage = db_select('file_usage', 'f')
-      ->fields('f')
-      ->condition('f.fid', $file->fid)
-      ->execute()
-      ->fetchAllAssoc('id');
-    $this->assertEqual(count($usage), 2, t('Created two records'));
-    $this->assertEqual($usage[1]->module, 'testing', t('Correct module'));
-    $this->assertEqual($usage[2]->module, 'testing', t('Correct module'));
-    $this->assertEqual($usage[1]->type, 'foo', t('Correct type'));
-    $this->assertEqual($usage[2]->type, 'bar', t('Correct type'));
-    $this->assertEqual($usage[1]->count, 1, t('Correct count'));
-    $this->assertEqual($usage[2]->count, 2, t('Correct count'));
-  }
-
-  /**
-   * Tests file_usage_delete().
-   */
-  function testRemoveUsage() {
-    $file = $this->createFile();
-    db_insert('file_usage')
-      ->fields(array(
-        'fid' => $file->fid,
-        'module' => 'testing',
-        'type' => 'bar',
-        'id' => 2,
-        'count' => 3,
-      ))
-      ->execute();
-
-    // Normal decrement.
-    file_usage_delete($file, 'testing', 'bar', 2);
-    $count = db_select('file_usage', 'f')
-      ->fields('f', array('count'))
-      ->condition('f.fid', $file->fid)
-      ->execute()
-      ->fetchField();
-    $this->assertEqual(2, $count, t('The count was decremented correctly.'));
-
-    // Multiple decrement and removal.
-    file_usage_delete($file, 'testing', 'bar', 2, 2);
-    $count = db_select('file_usage', 'f')
-      ->fields('f', array('count'))
-      ->condition('f.fid', $file->fid)
-      ->execute()
-      ->fetchField();
-    $this->assertIdentical(FALSE, $count, t('The count was removed entirely when empty.'));
-
-    // Non-existent decrement.
-    file_usage_delete($file, 'testing', 'bar', 2);
-    $count = db_select('file_usage', 'f')
-      ->fields('f', array('count'))
-      ->condition('f.fid', $file->fid)
-      ->execute()
-      ->fetchField();
-    $this->assertIdentical(FALSE, $count, t('Decrementing non-exist record complete.'));
-  }
-}
-
-/**
- * Tests the file_validate() function..
- */
-class FileValidateTest extends FileHookTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'File validate',
-      'description' => 'Tests the file_validate() function.',
-      'group' => 'File API',
-    );
-  }
-
-  /**
-   * Test that the validators passed into are checked.
-   */
-  function testCallerValidation() {
-    $file = $this->createFile();
-
-    // Empty validators.
-    $this->assertEqual(file_validate($file, array()), array(), t('Validating an empty array works successfully.'));
-    $this->assertFileHooksCalled(array('validate'));
-
-    // Use the file_test.module's test validator to ensure that passing tests
-    // return correctly.
-    file_test_reset();
-    file_test_set_return('validate', array());
-    $passing = array('file_test_validator' => array(array()));
-    $this->assertEqual(file_validate($file, $passing), array(), t('Validating passes.'));
-    $this->assertFileHooksCalled(array('validate'));
-
-    // Now test for failures in validators passed in and by hook_validate.
-    file_test_reset();
-    file_test_set_return('validate', array('Epic fail'));
-    $failing = array('file_test_validator' => array(array('Failed', 'Badly')));
-    $this->assertEqual(file_validate($file, $failing), array('Failed', 'Badly', 'Epic fail'), t('Validating returns errors.'));
-    $this->assertFileHooksCalled(array('validate'));
-  }
-}
-
-/**
- *  Tests the file_save_data() function.
- */
-class FileSaveDataTest extends FileHookTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'File save data',
-      'description' => 'Tests the file save data function.',
-      'group' => 'File API',
-    );
-  }
-
-  /**
-   * Test the file_save_data() function when no filename is provided.
-   */
-  function testWithoutFilename() {
-    $contents = $this->randomName(8);
-
-    $result = file_save_data($contents);
-    $this->assertTrue($result, t('Unnamed file saved correctly.'));
-
-    $this->assertEqual(file_default_scheme(), file_uri_scheme($result->uri), t("File was placed in Drupal's files directory."));
-    $this->assertEqual($result->filename, drupal_basename($result->uri), t("Filename was set to the file's basename."));
-    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of the file are correct.'));
-    $this->assertEqual($result->filemime, 'application/octet-stream', t('A MIME type was set.'));
-    $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('insert'));
-
-    // Verify that what was returned is what's in the database.
-    $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
-  }
-
-  /**
-   * Test the file_save_data() function when a filename is provided.
-   */
-  function testWithFilename() {
-    $contents = $this->randomName(8);
-
-    // Using filename with non-latin characters.
-    $filename = 'Текстовый файл.txt';
-
-    $result = file_save_data($contents, 'public://' . $filename);
-    $this->assertTrue($result, t('Unnamed file saved correctly.'));
-
-    $this->assertEqual('public', file_uri_scheme($result->uri), t("File was placed in Drupal's files directory."));
-    $this->assertEqual($filename, drupal_basename($result->uri), t('File was named correctly.'));
-    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of the file are correct.'));
-    $this->assertEqual($result->filemime, 'text/plain', t('A MIME type was set.'));
-    $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('insert'));
-
-    // Verify that what was returned is what's in the database.
-    $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
-  }
-
-  /**
-   * Test file_save_data() when renaming around an existing file.
-   */
-  function testExistingRename() {
-    // Setup a file to overwrite.
-    $existing = $this->createFile();
-    $contents = $this->randomName(8);
-
-    $result = file_save_data($contents, $existing->uri, FILE_EXISTS_RENAME);
-    $this->assertTrue($result, t("File saved successfully."));
-
-    $this->assertEqual('public', file_uri_scheme($result->uri), t("File was placed in Drupal's files directory."));
-    $this->assertEqual($result->filename, $existing->filename, t("Filename was set to the basename of the source, rather than that of the renamed file."));
-    $this->assertEqual($contents, file_get_contents($result->uri), t("Contents of the file are correct."));
-    $this->assertEqual($result->filemime, 'application/octet-stream', t("A MIME type was set."));
-    $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('insert'));
-
-    // Ensure that the existing file wasn't overwritten.
-    $this->assertDifferentFile($existing, $result);
-    $this->assertFileUnchanged($existing, file_load($existing->fid, TRUE));
-
-    // Verify that was returned is what's in the database.
-    $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
-  }
-
-  /**
-   * Test file_save_data() when replacing an existing file.
-   */
-  function testExistingReplace() {
-    // Setup a file to overwrite.
-    $existing = $this->createFile();
-    $contents = $this->randomName(8);
-
-    $result = file_save_data($contents, $existing->uri, FILE_EXISTS_REPLACE);
-    $this->assertTrue($result, t('File saved successfully.'));
-
-    $this->assertEqual('public', file_uri_scheme($result->uri), t("File was placed in Drupal's files directory."));
-    $this->assertEqual($result->filename, $existing->filename, t('Filename was set to the basename of the existing file, rather than preserving the original name.'));
-    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of the file are correct.'));
-    $this->assertEqual($result->filemime, 'application/octet-stream', t('A MIME type was set.'));
-    $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('load', 'update'));
-
-    // Verify that the existing file was re-used.
-    $this->assertSameFile($existing, $result);
-
-    // Verify that what was returned is what's in the database.
-    $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
-  }
-
-  /**
-   * Test that file_save_data() fails overwriting an existing file.
-   */
-  function testExistingError() {
-    $contents = $this->randomName(8);
-    $existing = $this->createFile(NULL, $contents);
-
-    // Check the overwrite error.
-    $result = file_save_data('asdf', $existing->uri, FILE_EXISTS_ERROR);
-    $this->assertFalse($result, t('Overwriting a file fails when FILE_EXISTS_ERROR is specified.'));
-    $this->assertEqual($contents, file_get_contents($existing->uri), t('Contents of existing file were unchanged.'));
-
-    // Check that no hooks were called while failing.
-    $this->assertFileHooksCalled(array());
-
-    // Ensure that the existing file wasn't overwritten.
-    $this->assertFileUnchanged($existing, file_load($existing->fid, TRUE));
-  }
-}
-
-/**
- * Tests for download/file transfer functions.
- */
-class FileDownloadTest extends FileTestCase {
-  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();
-  }
-}
-
-/**
- * Tests for file URL rewriting.
- */
-class FileURLRewritingTest extends FileTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'File URL rewriting',
-      'description' => 'Tests for file URL rewriting.',
-      'group' => 'File',
-    );
-  }
-
-  function setUp() {
-    parent::setUp('file_test');
-  }
-
-  /**
-   * Test the generating of rewritten shipped file URLs.
-   */
-  function testShippedFileURL()  {
-    // 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).
-
-    // Test alteration of file URLs to use a CDN.
-    variable_set('file_test_hook_file_url_alter', 'cdn');
-    $filepath = 'core/misc/jquery.js';
-    $url = file_create_url($filepath);
-    $this->assertEqual(FILE_URL_TEST_CDN_1 . '/' . $filepath, $url, t('Correctly generated a CDN URL for a shipped file.'));
-    $filepath = 'core/misc/favicon.ico';
-    $url = file_create_url($filepath);
-    $this->assertEqual(FILE_URL_TEST_CDN_2 . '/' . $filepath, $url, t('Correctly generated a CDN URL for a shipped file.'));
-
-    // Test alteration of file URLs to use root-relative URLs.
-    variable_set('file_test_hook_file_url_alter', 'root-relative');
-    $filepath = 'core/misc/jquery.js';
-    $url = file_create_url($filepath);
-    $this->assertEqual(base_path() . '/' . $filepath, $url, t('Correctly generated a root-relative URL for a shipped file.'));
-    $filepath = 'core/misc/favicon.ico';
-    $url = file_create_url($filepath);
-    $this->assertEqual(base_path() . '/' . $filepath, $url, t('Correctly generated a root-relative URL for a shipped file.'));
-
-    // Test alteration of file URLs to use protocol-relative URLs.
-    variable_set('file_test_hook_file_url_alter', 'protocol-relative');
-    $filepath = 'core/misc/jquery.js';
-    $url = file_create_url($filepath);
-    $this->assertEqual('/' . base_path() . '/' . $filepath, $url, t('Correctly generated a protocol-relative URL for a shipped file.'));
-    $filepath = 'core/misc/favicon.ico';
-    $url = file_create_url($filepath);
-    $this->assertEqual('/' . base_path() . '/' . $filepath, $url, t('Correctly generated a protocol-relative URL for a shipped file.'));
-  }
-
-  /**
-   * Test the generating of rewritten public created file URLs.
-   */
-  function testPublicCreatedFileURL() {
-    // Test generating an URL to a created file.
-
-    // Test alteration of file URLs to use a CDN.
-    variable_set('file_test_hook_file_url_alter', 'cdn');
-    $file = $this->createFile();
-    $url = file_create_url($file->uri);
-    $public_directory_path = file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath();
-    $this->assertEqual(FILE_URL_TEST_CDN_2 . '/' . $public_directory_path . '/' . $file->filename, $url, t('Correctly generated a CDN URL for a created file.'));
-
-    // Test alteration of file URLs to use root-relative URLs.
-    variable_set('file_test_hook_file_url_alter', 'root-relative');
-    $file = $this->createFile();
-    $url = file_create_url($file->uri);
-    $this->assertEqual(base_path() . '/' . $public_directory_path . '/' . $file->filename, $url, t('Correctly generated a root-relative URL for a created file.'));
-
-    // Test alteration of file URLs to use a protocol-relative URLs.
-    variable_set('file_test_hook_file_url_alter', 'protocol-relative');
-    $file = $this->createFile();
-    $url = file_create_url($file->uri);
-    $this->assertEqual('/' . base_path() . '/' . $public_directory_path . '/' . $file->filename, $url, t('Correctly generated a protocol-relative URL for a created file.'));
-  }
-}
-
-/**
- * Tests for file_munge_filename() and file_unmunge_filename().
- */
-class FileNameMungingTest extends FileTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'File naming',
-      'description' => 'Test filename munging and unmunging.',
-      'group' => 'File API',
-    );
-  }
-
-  function setUp() {
-    parent::setUp();
-    $this->bad_extension = 'php';
-    $this->name = $this->randomName() . '.' . $this->bad_extension . '.txt';
-  }
-
-  /**
-   * Create a file and munge/unmunge the name.
-   */
-  function testMunging() {
-    // Disable insecure uploads.
-    variable_set('allow_insecure_uploads', 0);
-    $munged_name = file_munge_filename($this->name, '', TRUE);
-    $messages = drupal_get_messages();
-    $this->assertTrue(in_array(t('For security reasons, your upload has been renamed to %filename.', array('%filename' => $munged_name)), $messages['status']), t('Alert properly set when a file is renamed.'));
-    $this->assertNotEqual($munged_name, $this->name, t('The new filename (%munged) has been modified from the original (%original)', array('%munged' => $munged_name, '%original' => $this->name)));
-  }
-
-  /**
-   * If the allow_insecure_uploads variable evaluates to true, the file should
-   * come out untouched, no matter how evil the filename.
-   */
-  function testMungeIgnoreInsecure() {
-    variable_set('allow_insecure_uploads', 1);
-    $munged_name = file_munge_filename($this->name, '');
-    $this->assertIdentical($munged_name, $this->name, t('The original filename (%original) matches the munged filename (%munged) when insecure uploads are enabled.', array('%munged' => $munged_name, '%original' => $this->name)));
-  }
-
-  /**
-   * White listed extensions are ignored by file_munge_filename().
-   */
-  function testMungeIgnoreWhitelisted() {
-    // Declare our extension as whitelisted.
-    $munged_name = file_munge_filename($this->name, $this->bad_extension);
-    $this->assertIdentical($munged_name, $this->name, t('The new filename (%munged) matches the original (%original) once the extension has been whitelisted.', array('%munged' => $munged_name, '%original' => $this->name)));
-  }
-
-  /**
-   * Ensure that unmunge gets your name back.
-   */
-  function testUnMunge() {
-    $munged_name = file_munge_filename($this->name, '', FALSE);
-    $unmunged_name = file_unmunge_filename($munged_name);
-    $this->assertIdentical($unmunged_name, $this->name, t('The unmunged (%unmunged) filename matches the original (%original)', array('%unmunged' => $unmunged_name, '%original' => $this->name)));
-  }
-}
-
-/**
- * Tests for file_get_mimetype().
- */
-class FileMimeTypeTest extends WebTestBase {
-  function setUp() {
-    parent::setUp('file_test');
-  }
-
-  public static function getInfo() {
-    return array(
-      'name' => 'File mimetypes',
-      'description' => 'Test filename mimetype detection.',
-      'group' => 'File API',
-    );
-  }
-
-  /**
-   * Test mapping of mimetypes from filenames.
-   */
-  public function testFileMimeTypeDetection() {
-    $prefix = 'public://';
-
-    $test_case = array(
-      'test.jar' => 'application/java-archive',
-      'test.jpeg' => 'image/jpeg',
-      'test.JPEG' => 'image/jpeg',
-      'test.jpg' => 'image/jpeg',
-      'test.jar.jpg' => 'image/jpeg',
-      'test.jpg.jar' => 'application/java-archive',
-      'test.pcf.Z' => 'application/x-font',
-      'pcf.z' => 'application/octet-stream',
-      'jar' => 'application/octet-stream',
-      'some.junk' => 'application/octet-stream',
-      'foo.file_test_1' => 'madeup/file_test_1',
-      'foo.file_test_2' => 'madeup/file_test_2',
-      'foo.doc' => 'madeup/doc',
-      'test.ogg' => 'audio/ogg',
-    );
-
-    // Test using default mappings.
-    foreach ($test_case as $input => $expected) {
-      // Test stream [URI].
-      $output = file_get_mimetype($prefix . $input);
-      $this->assertIdentical($output, $expected, t('Mimetype for %input is %output (expected: %expected).', array('%input' => $input, '%output' => $output, '%expected' => $expected)));
-
-      // Test normal path equivalent
-      $output = file_get_mimetype($input);
-      $this->assertIdentical($output, $expected, t('Mimetype (using default mappings) for %input is %output (expected: %expected).', array('%input' => $input, '%output' => $output, '%expected' => $expected)));
-    }
-
-    // Now test passing in the map.
-    $mapping = array(
-      'mimetypes' => array(
-        0 => 'application/java-archive',
-        1 => 'image/jpeg',
-      ),
-      'extensions' => array(
-         'jar' => 0,
-         'jpg' => 1,
-      )
-    );
-
-    $test_case = array(
-      'test.jar' => 'application/java-archive',
-      'test.jpeg' => 'application/octet-stream',
-      'test.jpg' => 'image/jpeg',
-      'test.jar.jpg' => 'image/jpeg',
-      'test.jpg.jar' => 'application/java-archive',
-      'test.pcf.z' => 'application/octet-stream',
-      'pcf.z' => 'application/octet-stream',
-      'jar' => 'application/octet-stream',
-      'some.junk' => 'application/octet-stream',
-      'foo.file_test_1' => 'application/octet-stream',
-      'foo.file_test_2' => 'application/octet-stream',
-      'foo.doc' => 'application/octet-stream',
-      'test.ogg' => 'application/octet-stream',
-    );
-
-    foreach ($test_case as $input => $expected) {
-      $output = file_get_mimetype($input, $mapping);
-      $this->assertIdentical($output, $expected, t('Mimetype (using passed-in mappings) for %input is %output (expected: %expected).', array('%input' => $input, '%output' => $output, '%expected' => $expected)));
-    }
-  }
-}
-
-/**
- * Tests stream wrapper functions.
- */
-class StreamWrapperTest extends WebTestBase {
-
-  protected $scheme = 'dummy';
-  protected $classname = 'DrupalDummyStreamWrapper';
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Stream wrappers',
-      'description' => 'Tests stream wrapper functions.',
-      'group' => 'File API',
-    );
-  }
-
-  function setUp() {
-    parent::setUp('file_test');
-    drupal_static_reset('file_get_stream_wrappers');
-  }
-
-  function tearDown() {
-    parent::tearDown();
-    stream_wrapper_unregister($this->scheme);
-  }
-
-  /**
-   * Test the getClassName() function.
-   */
-  function testGetClassName() {
-    // Check the dummy scheme.
-    $this->assertEqual($this->classname, file_stream_wrapper_get_class($this->scheme), t('Got correct class name for dummy scheme.'));
-    // Check core's scheme.
-    $this->assertEqual('Drupal\Core\StreamWrapper\PublicStream', file_stream_wrapper_get_class('public'), t('Got correct class name for public scheme.'));
-  }
-
-  /**
-   * Test the file_stream_wrapper_get_instance_by_scheme() function.
-   */
-  function testGetInstanceByScheme() {
-    $instance = file_stream_wrapper_get_instance_by_scheme($this->scheme);
-    $this->assertEqual($this->classname, get_class($instance), t('Got correct class type for dummy scheme.'));
-
-    $instance = file_stream_wrapper_get_instance_by_scheme('public');
-    $this->assertEqual('Drupal\Core\StreamWrapper\PublicStream', get_class($instance), t('Got correct class type for public scheme.'));
-  }
-
-  /**
-   * Test the URI and target functions.
-   */
-  function testUriFunctions() {
-    $instance = file_stream_wrapper_get_instance_by_uri($this->scheme . '://foo');
-    $this->assertEqual($this->classname, get_class($instance), t('Got correct class type for dummy URI.'));
-
-    $instance = file_stream_wrapper_get_instance_by_uri('public://foo');
-    $this->assertEqual('Drupal\Core\StreamWrapper\PublicStream', get_class($instance), t('Got correct class type for public URI.'));
-
-    // Test file_uri_target().
-    $this->assertEqual(file_uri_target('public://foo/bar.txt'), 'foo/bar.txt', t('Got a valid stream target from public://foo/bar.txt.'));
-    $this->assertFalse(file_uri_target('foo/bar.txt'), t('foo/bar.txt is not a valid stream.'));
-
-    // Test file_build_uri() and
-    // Drupal\Core\StreamWrapper\LocalStream::getDirectoryPath().
-    $this->assertEqual(file_build_uri('foo/bar.txt'), 'public://foo/bar.txt', t('Expected scheme was added.'));
-    $this->assertEqual(file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath(), variable_get('file_public_path'), t('Expected default directory path was returned.'));
-    $this->assertEqual(file_stream_wrapper_get_instance_by_scheme('temporary')->getDirectoryPath(), variable_get('file_temporary_path'), t('Expected temporary directory path was returned.'));
-
-    variable_set('file_default_scheme', 'private');
-    $this->assertEqual(file_build_uri('foo/bar.txt'), 'private://foo/bar.txt', t('Got a valid URI from foo/bar.txt.'));
-  }
-
-  /**
-   * Test the scheme functions.
-   */
-  function testGetValidStreamScheme() {
-    $this->assertEqual('foo', file_uri_scheme('foo://pork//chops'), t('Got the correct scheme from foo://asdf'));
-    $this->assertTrue(file_stream_wrapper_valid_scheme(file_uri_scheme('public://asdf')), t('Got a valid stream scheme from public://asdf'));
-    $this->assertFalse(file_stream_wrapper_valid_scheme(file_uri_scheme('foo://asdf')), t('Did not get a valid stream scheme from foo://asdf'));
-  }
-}
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 6a04d7c..ee10961 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -1,7 +1,7 @@
 <?php
 
 use Drupal\Core\Database\Query\SelectInterface;
-use Drupal\Core\File\File;
+use Drupal\file\File;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 
 /**
