You are here

file_entity.test in File Entity (fieldable files) 7.3

Same filename and directory in other branches
  1. 7.2 file_entity.test

Test integration for the file_entity module.

File

file_entity.test
View source
<?php

/**
 * @file
 * Test integration for the file_entity module.
 */
class FileEntityTestHelper extends DrupalWebTestCase {
  function setUp() {
    $modules = func_get_args();
    if (isset($modules[0]) && is_array($modules[0])) {
      $modules = $modules[0];
    }
    $modules[] = 'file_entity';
    parent::setUp($modules);
  }

  /**
   * Retrieves a sample file of the specified type.
   */
  function getTestFile($type_name, $size = NULL) {

    // Get a file to upload.
    $file = current($this
      ->drupalGetTestFiles($type_name, $size));

    // Add a filesize property to files as would be read by file_load().
    $file->filesize = filesize($file->uri);
    return $file;
  }

  /**
   * Retrieves the fid of the last inserted file.
   */
  function getLastFileId() {
    return (int) db_query('SELECT MAX(fid) FROM {file_managed}')
      ->fetchField();
  }

  /**
   * Get a file from the database based on its filename.
   *
   * @param $filename
   *   A file filename, usually generated by $this->randomName().
   * @param $reset
   *   (optional) Whether to reset the internal file_load() cache.
   *
   * @return
   *   A file object matching $filename.
   */
  function getFileByFilename($filename, $reset = FALSE) {
    $files = file_load_multiple(array(), array(
      'filename' => $filename,
    ), $reset);

    // Load the first file returned from the database.
    $returned_file = reset($files);
    return $returned_file;
  }
  protected function createFileEntity($settings = array()) {

    // Populate defaults array.
    $settings += array(
      'filepath' => 'Файл для тестирования ' . $this
        ->randomName(),
      // Prefix with non-latin characters to ensure that all file-related tests work with international filenames.
      'filemime' => 'text/plain',
      'uid' => 1,
      'timestamp' => REQUEST_TIME,
      'status' => FILE_STATUS_PERMANENT,
      'contents' => "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data.",
      'scheme' => file_default_scheme(),
      'type' => NULL,
    );
    $filepath = $settings['scheme'] . '://' . $settings['filepath'];
    file_put_contents($filepath, $settings['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 = $settings['filemime'];
    $file->uid = $settings['uid'];
    $file->timestamp = $settings['timestamp'];
    $file->filesize = filesize($file->uri);
    $file->status = $settings['status'];
    $file->type = $settings['type'];

    // The file type is used as a bundle key, and therefore, must not be NULL.
    if (!isset($file->type)) {
      $file->type = FILE_TYPE_NONE;
    }

    // If the file isn't already assigned a real type, determine what type should
    // be assigned to it.
    if ($file->type === FILE_TYPE_NONE) {
      $type = file_get_type($file);
      if (isset($type)) {
        $file->type = $type;
      }
    }

    // Write the record directly rather than calling file_save() 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 $file;
  }
  protected function createFileType($overrides = array()) {
    $type = new stdClass();
    $type->type = 'test';
    $type->label = "Test";
    $type->description = '';
    $type->mimetypes = array(
      'image/jpeg',
      'image/gif',
      'image/png',
      'image/tiff',
    );
    foreach ($overrides as $k => $v) {
      $type->{$k} = $v;
    }
    file_type_save($type);
    return $type;
  }

  /**
   * Overrides DrupalWebTestCase::drupalGetToken() to support the hash salt.
   *
   * @todo Remove when http://drupal.org/node/1555862 is fixed in core.
   */
  protected function drupalGetToken($value = '') {
    $private_key = drupal_get_private_key();
    return drupal_hmac_base64($value, $this->session_id . $private_key . drupal_get_hash_salt());
  }

}

/**
 * Tests file type classification functionality.
 */
class FileEntityFileTypeClassificationTestCase extends DrupalWebTestCase {
  public static function getInfo() {
    return array(
      'name' => 'File entity classification',
      'description' => 'Test existing file entity classification functionality.',
      'group' => 'File entity',
    );
  }
  function setUp() {
    parent::setUp();
  }

  /**
   * Test that existing files are properly classified by file type.
   */
  function testFileTypeClassification() {

    // Get test text and image files.
    $file = current($this
      ->drupalGetTestFiles('text'));
    $text_file = file_save($file);
    $file = current($this
      ->drupalGetTestFiles('image'));
    $image_file = file_save($file);

    // Enable file entity which adds adds a file type property to files and
    // queues up existing files for classification.
    module_enable(array(
      'file_entity',
    ));

    // Existing files have yet to be classified and should have an undefined
    // file type.
    $file_type = $this
      ->getFileType($text_file);
    $this
      ->assertEqual($file_type['type'], 'undefined', t('The text file has an undefined file type.'));
    $file_type = $this
      ->getFileType($image_file);
    $this
      ->assertEqual($file_type['type'], 'undefined', t('The image file has an undefined file type.'));

    // The classification queue is processed during cron runs. Run cron to
    // trigger the classification process.
    $this
      ->cronRun();

    // The classification process should assign a file type to any file whose
    // MIME type is assigned to a file type. Check to see if each file was
    // assigned a proper file type.
    $file_type = $this
      ->getFileType($text_file);
    $this
      ->assertEqual($file_type['type'], 'document', t('The text file was properly assigned the Document file type.'));
    $file_type = $this
      ->getFileType($image_file);
    $this
      ->assertEqual($file_type['type'], 'image', t('The image file was properly assigned the Image file type.'));
  }

  /**
   * Get the file type of a given file.
   *
   * @param $file
   *   A file object.
   *
   * @return
   *   The file's file type as a string.
   */
  function getFileType($file) {
    $type = db_select('file_managed', 'fm')
      ->fields('fm', array(
      'type',
    ))
      ->condition('fid', $file->fid, '=')
      ->execute()
      ->fetchAssoc();
    return $type;
  }

}

/**
 * Tests basic file entity functionality.
 */
class FileEntityUnitTestCase extends FileEntityTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'File entity unit tests',
      'description' => 'Test basic file entity functionality.',
      'group' => 'File entity',
    );
  }

  /**
   * Regression tests for core issue http://drupal.org/node/1239376.
   */
  function testMimeTypeMappings() {
    $tests = array(
      'public://test.ogg' => 'audio/ogg',
      'public://test.mkv' => 'video/x-m4v',
      'public://test.mka' => 'audio/x-matroska',
      'public://test.mkv' => 'video/x-matroska',
      'public://test.webp' => 'image/webp',
    );
    foreach ($tests as $input => $expected) {
      $this
        ->assertEqual(file_get_mimetype($input), $expected);
    }
  }

  /**
   * Tests basic file entity properties.
   */
  function testFileEntity() {

    // Save a raw file, turning it into a file entity.
    $file = $this
      ->getTestFile('text');
    $file->uid = 1;
    $file->status = FILE_STATUS_PERMANENT;
    file_save($file);

    // Test entity ID, revision ID, and bundle.
    $ids = entity_extract_ids('file', $file);
    $this
      ->assertIdentical($ids, array(
      $file->fid,
      NULL,
      'document',
    ));

    // Test the entity URI callback.
    $uri = entity_uri('file', $file);
    $this
      ->assertEqual($uri['path'], "file/{$file->fid}");
  }

  /**
   * Tests storing image height and width as file metadata.
   */
  function testImageDimensions() {

    // Test hook_file_insert().
    $file = current($this
      ->drupalGetTestFiles('image'));
    $image_file = file_save($file);
    $this
      ->assertTrue(isset($image_file->metadata['height']), 'Image height retrieved on file_save() for an image file.');
    $this
      ->assertTrue(isset($image_file->metadata['width']), 'Image width retrieved on file_save() for an image file.');
    $file = current($this
      ->drupalGetTestFiles('text'));
    $text_file = file_save($file);
    $this
      ->assertFalse(isset($text_file->metadata['height']), 'No image height retrieved on file_save() for an text file.');
    $this
      ->assertFalse(isset($text_file->metadata['width']), 'No image width retrieved on file_save() for an text file.');

    // Test hook_file_load().
    // Clear the cache and load fresh files objects to test file_load behavior.
    entity_get_controller('file')
      ->resetCache();
    $file = file_load($image_file->fid);
    $this
      ->assertTrue(isset($file->metadata['height']), 'Image dimensions retrieved on file_load() for an image file.');
    $this
      ->assertTrue(isset($file->metadata['width']), 'Image dimensions retrieved on file_load() for an image file.');
    $this
      ->assertEqual($file->metadata['height'], $image_file->metadata['height'], 'Loaded image height is equal to saved image height.');
    $this
      ->assertEqual($file->metadata['width'], $image_file->metadata['width'], 'Loaded image width is equal to saved image width.');
    $file = file_load($text_file->fid);
    $this
      ->assertFalse(isset($file->metadata['height']), 'No image height retrieved on file_load() for an text file.');
    $this
      ->assertFalse(isset($file->metadata['width']), 'No image width retrieved on file_load() for an text file.');

    // Test hook_file_update().
    // Load the first image file and resize it.
    $height = $image_file->metadata['width'] / 2;
    $width = $image_file->metadata['height'] / 2;
    $image = image_load($image_file->uri);
    image_resize($image, $width, $height);
    image_save($image);
    file_save($image_file);
    $this
      ->assertEqual($image_file->metadata['height'], $height, 'Image file height updated by file_save().');
    $this
      ->assertEqual($image_file->metadata['width'], $width, 'Image file width updated by file_save().');

    // Clear the cache and reload the file.
    entity_get_controller('file')
      ->resetCache();
    $file = file_load($image_file->fid);
    $this
      ->assertEqual($file->metadata['height'], $height, 'Updated image height retrieved by file_load().');
    $this
      ->assertEqual($file->metadata['width'], $width, 'Updated image width retrieved by file_load().');

    // Verify that the image dimension metadata is removed on file deletion.
    file_delete($file, TRUE);
    $this
      ->assertFalse(db_query('SELECT COUNT(*) FROM {file_metadata} WHERE fid = :fid', array(
      ':fid' => 'fid',
    ))
      ->fetchField(), 'Row deleted in {file_metadata} on file_delete().');
  }

}

/**
 * Tests editing existing file entities.
 */
class FileEntityEditTestCase extends FileEntityTestHelper {
  protected $web_user;
  protected $admin_user;
  public static function getInfo() {
    return array(
      'name' => 'File entity edit',
      'description' => 'Create a file and test file edit functionality.',
      'group' => 'File entity',
    );
  }
  function setUp() {
    parent::setUp();
    $this->web_user = $this
      ->drupalCreateUser(array(
      'edit own document files',
      'create files',
    ));
    $this->admin_user = $this
      ->drupalCreateUser(array(
      'bypass file access',
      'administer files',
    ));
  }

  /**
   * Check file edit functionality.
   */
  function testFileEntityEdit() {
    $this
      ->drupalLogin($this->web_user);
    $test_file = $this
      ->getTestFile('text');
    $name_key = "filename";

    // Create file to edit.
    $edit = array();
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
    $this
      ->drupalPost('file/add', $edit, t('Next'));
    if ($this
      ->xpath('//input[@name="scheme"]')) {
      $this
        ->drupalPost(NULL, array(), t('Next'));
    }

    // Check that the file exists in the database.
    $file = $this
      ->getFileByFilename($test_file->filename);
    $this
      ->assertTrue($file, t('File found in database.'));

    // Check that "edit" link points to correct page.
    $this
      ->clickLink(t('Edit'));
    $edit_url = url("file/{$file->fid}/edit", array(
      'absolute' => TRUE,
    ));
    $actual_url = $this
      ->getURL();
    $this
      ->assertEqual($edit_url, $actual_url, t('On edit page.'));

    // Check that the name field is displayed with the correct value.
    $active = '<span class="element-invisible">' . t('(active tab)') . '</span>';
    $link_text = t('!local-task-title!active', array(
      '!local-task-title' => t('Edit'),
      '!active' => $active,
    ));
    $this
      ->assertText(strip_tags($link_text), 0, t('Edit tab found and marked active.'));
    $this
      ->assertFieldByName($name_key, $file->filename, t('Name field displayed.'));

    // The user does not have "delete" permissions so no delete button should be found.
    $this
      ->assertNoFieldByName('op', t('Delete'), 'Delete button not found.');

    // Edit the content of the file.
    $edit = array();
    $edit[$name_key] = $this
      ->randomName(8);

    // Stay on the current page, without reloading.
    $this
      ->drupalPost(NULL, $edit, t('Save'));

    // Check that the name field is displayed with the updated values.
    $this
      ->assertText($edit[$name_key], t('Name displayed.'));
  }

  /**
   * Check changing file associated user fields.
   */
  function testFileEntityAssociatedUser() {
    $this
      ->drupalLogin($this->admin_user);

    // Create file to edit.
    $test_file = $this
      ->getTestFile('text');
    $name_key = "filename";
    $edit = array();
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
    $this
      ->drupalPost('file/add', $edit, t('Next'));

    // Check that the file was associated with the currently logged in user.
    $file = $this
      ->getFileByFilename($test_file->filename);
    $this
      ->assertIdentical($file->uid, $this->admin_user->uid, 'File associated with admin user.');

    // Try to change the 'associated user' field to an invalid user name.
    $edit = array(
      'name' => 'invalid-name',
    );
    $this
      ->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
    $this
      ->assertText('The username invalid-name does not exist.');

    // Change the associated user field to an empty string, which should assign
    // association to the anonymous user (uid 0).
    $edit['name'] = '';
    $this
      ->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
    $file = file_load($file->fid);
    $this
      ->assertIdentical($file->uid, '0', 'File associated with anonymous user.');

    // Change the associated user field to another user's name (that is not
    // logged in).
    $edit['name'] = $this->web_user->name;
    $this
      ->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
    $file = file_load($file->fid);
    $this
      ->assertIdentical($file->uid, $this->web_user->uid, 'File associated with normal user.');

    // Check that normal users cannot change the associated user information.
    $this
      ->drupalLogin($this->web_user);
    $this
      ->drupalGet('file/' . $file->fid . '/edit');
    $this
      ->assertNoFieldByName('name');
  }

}

/**
 * Tests creating new file entities through the file upload wizard.
 */
class FileEntityUploadWizardTestCase extends FileEntityTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'File entity upload wizard',
      'description' => 'Upload a file using the multi-step wizard.',
      'group' => 'File entity',
      'dependencies' => array(
        'token',
      ),
    );
  }
  function setUp() {
    parent::setUp('token');

    // Disable the private file system which is automatically enabled by
    // DrupalTestCase so we can test the upload wizard correctly.
    variable_del('file_private_path');
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
      'view own private files',
    ));
    $this
      ->drupalLogin($web_user);
  }

  /**
   * Test the basic file upload wizard functionality.
   */
  function testFileEntityUploadWizardBasic() {
    $test_file = $this
      ->getTestFile('text');

    // Step 1: Upload a basic document file.
    $edit = array();
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
    $this
      ->drupalPost('file/add', $edit, t('Next'));

    // Check that the file exists in the database.
    $fid = $this
      ->getLastFileId();
    $file = file_load($fid);
    $this
      ->assertTrue($file, t('File found in database.'));

    // Check that the document file has been uploaded.
    $this
      ->assertRaw(t('!type %name was uploaded.', array(
      '!type' => 'Document',
      '%name' => $file->filename,
    )), t('Document file uploaded.'));
  }

  /**
   * Test the file upload wizard type step.
   */
  function testFileEntityUploadWizardTypes() {
    $test_file = $this
      ->getTestFile('text');

    // Create multiple file types with the same mime types.
    $this
      ->createFileType(array(
      'type' => 'document1',
      'label' => 'Document 1',
      'mimetypes' => array(
        'text/plain',
      ),
    ));
    $this
      ->createFileType(array(
      'type' => 'document2',
      'label' => 'Document 2',
      'mimetypes' => array(
        'text/plain',
      ),
    ));

    // Step 1: Upload a basic document file.
    $edit = array();
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
    $this
      ->drupalPost('file/add', $edit, t('Next'));

    // Step 2: File type selection.
    $edit = array();
    $edit['type'] = 'document2';
    $this
      ->drupalPost(NULL, $edit, t('Next'));

    // Check that the file exists in the database.
    $fid = $this
      ->getLastFileId();
    $file = file_load($fid);
    $this
      ->assertTrue($file, t('File found in database.'));

    // Check that the document file has been uploaded.
    $this
      ->assertRaw(t('!type %name was uploaded.', array(
      '!type' => 'Document 2',
      '%name' => $file->filename,
    )), t('Document 2 file uploaded.'));
  }

  /**
   * Test the file upload wizard scheme step.
   */
  function testFileEntityUploadWizardSchemes() {
    $test_file = $this
      ->getTestFile('text');

    // Enable the private file system.
    variable_set('file_private_path', $this->private_files_directory);

    // Step 1: Upload a basic document file.
    $edit = array();
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
    $this
      ->drupalPost('file/add', $edit, t('Next'));

    // Step 3: Scheme selection.
    $edit = array();
    $edit['scheme'] = 'private';
    $this
      ->drupalPost(NULL, $edit, t('Next'));

    // Check that the file exists in the database.
    $fid = $this
      ->getLastFileId();
    $file = file_load($fid);
    $this
      ->assertTrue($file, t('File found in database.'));

    // Check that the document file has been uploaded.
    $this
      ->assertRaw(t('!type %name was uploaded.', array(
      '!type' => 'Document',
      '%name' => $file->filename,
    )), t('Document file uploaded.'));
  }

  /**
   * Test the file upload wizard field step.
   */
  function testFileEntityUploadWizardFields() {
    $test_file = $this
      ->getTestFile('image');
    $filename = $this
      ->randomName();
    $alt = $this
      ->randomName();
    $title = $this
      ->randomName();

    // Step 1: Upload a basic image file.
    $edit = array();
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
    $this
      ->drupalPost('file/add', $edit, t('Next'));

    // Step 4: Attached fields.
    $edit = array();
    $edit['filename'] = $filename;
    $edit['field_file_image_alt_text[' . LANGUAGE_NONE . '][0][value]'] = $alt;
    $edit['field_file_image_title_text[' . LANGUAGE_NONE . '][0][value]'] = $title;
    $this
      ->drupalPost(NULL, $edit, t('Save'));

    // Check that the file exists in the database.
    $fid = $this
      ->getLastFileId();
    $file = file_load($fid);
    $this
      ->assertTrue($file, t('File found in database.'));

    // Check that the image file has been uploaded.
    $this
      ->assertRaw(t('!type %name was uploaded.', array(
      '!type' => 'Image',
      '%name' => $filename,
    )), t('Image file uploaded.'));

    // Check that the alt and title text was loaded from the fields.
    $this
      ->assertEqual($file->alt, $alt, t('Alt text was stored as file metadata.'));
    $this
      ->assertEqual($file->title, $title, t('Title text was stored as file metadata.'));
  }

  /**
   * Test skipping each of the file upload wizard steps.
   */
  function testFileEntityUploadWizardStepSkipping() {
    $test_file = $this
      ->getTestFile('image');
    $filename = $this
      ->randomName();

    // Ensure that the file is affected by every step.
    variable_set('file_private_path', $this->private_files_directory);
    $this
      ->createFileType(array(
      'type' => 'image1',
      'label' => 'Image 1',
      'mimetypes' => array(
        'image/jpeg',
        'image/gif',
        'image/png',
        'image/tiff',
      ),
    ));
    $this
      ->createFileType(array(
      'type' => 'image2',
      'label' => 'Image 2',
      'mimetypes' => array(
        'image/jpeg',
        'image/gif',
        'image/png',
        'image/tiff',
      ),
    ));
    $field_name = drupal_strtolower($this
      ->randomName() . '_field_name');
    $field = array(
      'field_name' => $field_name,
      'type' => 'text',
    );
    field_create_field($field);
    $instance = array(
      'field_name' => $field_name,
      'entity_type' => 'file',
      'bundle' => 'image2',
      'label' => $this
        ->randomName() . '_label',
    );
    field_create_instance($instance);

    // Test skipping each upload wizard step.
    foreach (array(
      'types',
      'schemes',
      'fields',
    ) as $step) {

      // Step to skip.
      switch ($step) {
        case 'types':
          variable_set('file_entity_file_upload_wizard_skip_file_type', TRUE);
          break;
        case 'schemes':
          variable_set('file_entity_file_upload_wizard_skip_scheme', TRUE);
          break;
        case 'fields':
          variable_set('file_entity_file_upload_wizard_skip_fields', TRUE);
          break;
      }

      // Step 1: Upload a basic image file.
      $edit = array();
      $edit['files[upload]'] = drupal_realpath($test_file->uri);
      $this
        ->drupalPost('file/add', $edit, t('Next'));

      // Step 2: File type selection.
      if ($step != 'types') {
        $edit = array();
        $edit['type'] = 'image2';
        $this
          ->drupalPost(NULL, $edit, t('Next'));
      }

      // Step 3: Scheme selection.
      if ($step != 'schemes') {
        $edit = array();
        $edit['scheme'] = 'private';
        $this
          ->drupalPost(NULL, $edit, t('Next'));
      }

      // Step 4: Attached fields.
      if ($step != 'fields') {

        // Skipping file type selection essentially skips this step as well
        // because the file will not be assigned a type so no fields will be
        // available.
        if ($step != 'types') {
          $edit = array();
          $edit['filename'] = $filename;
          $edit[$field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $this
            ->randomName();
          $this
            ->drupalPost(NULL, $edit, t('Save'));
        }
      }

      // Check that the file exists in the database.
      $fid = $this
        ->getLastFileId();
      $file = file_load($fid);
      $this
        ->assertTrue($file, t('File found in database.'));

      // Determine the file's file type.
      $type = file_type_load($file->type);

      // Check that the image file has been uploaded.
      $this
        ->assertRaw(t('!type %name was uploaded.', array(
        '!type' => $type->label,
        '%name' => $file->filename,
      )), t('Image file uploaded.'));

      // Reset 'skip' variables.
      variable_del('file_entity_file_upload_wizard_skip_file_type');
      variable_del('file_entity_file_upload_wizard_skip_scheme');
      variable_del('file_entity_file_upload_wizard_skip_fields');
    }
  }

}

/**
 * Test file administration page functionality.
 */
class FileEntityAdminTestCase extends FileEntityTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'File administration',
      'description' => 'Test file administration page functionality.',
      'group' => 'File entity',
    );
  }
  function setUp() {
    parent::setUp();

    // Remove the "view files" permission which is set
    // by default for all users so we can test this permission
    // correctly.
    $roles = user_roles();
    foreach ($roles as $rid => $role) {
      user_role_revoke_permissions($rid, array(
        'view files',
      ));
    }
    $this->admin_user = $this
      ->drupalCreateUser(array(
      'administer files',
      'bypass file access',
    ));
    $this->base_user_1 = $this
      ->drupalCreateUser(array(
      'administer files',
    ));
    $this->base_user_2 = $this
      ->drupalCreateUser(array(
      'administer files',
      'view own private files',
    ));
    $this->base_user_3 = $this
      ->drupalCreateUser(array(
      'administer files',
      'view private files',
    ));
    $this->base_user_4 = $this
      ->drupalCreateUser(array(
      'administer files',
      'edit any document files',
      'delete any document files',
      'edit any image files',
      'delete any image files',
    ));
  }

  /**
   * Tests that the table sorting works on the files admin pages.
   */
  function testFilesAdminSort() {
    $this
      ->drupalLogin($this->admin_user);
    $i = 0;
    foreach (array(
      'dd',
      'aa',
      'DD',
      'bb',
      'cc',
      'CC',
      'AA',
      'BB',
    ) as $prefix) {
      $this
        ->createFileEntity(array(
        'filepath' => $prefix . $this
          ->randomName(6),
        'timestamp' => $i,
      ));
      $i++;
    }

    // Test that the default sort by file_managed.timestamp DESC actually fires properly.
    $files_query = db_select('file_managed', 'fm')
      ->fields('fm', array(
      'fid',
    ))
      ->orderBy('timestamp', 'DESC')
      ->execute()
      ->fetchCol();
    $files_form = array();
    $this
      ->drupalGet('admin/content/file');
    foreach ($this
      ->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
      $files_form[] = $input;
    }
    $this
      ->assertEqual($files_query, $files_form, 'Files are sorted in the form according to the default query.');

    // Compare the rendered HTML node list to a query for the files ordered by
    // filename to account for possible database-dependent sort order.
    $files_query = db_select('file_managed', 'fm')
      ->fields('fm', array(
      'fid',
    ))
      ->orderBy('filename')
      ->execute()
      ->fetchCol();
    $files_form = array();
    $this
      ->drupalGet('admin/content/file', array(
      'query' => array(
        'sort' => 'asc',
        'order' => 'Title',
      ),
    ));
    foreach ($this
      ->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
      $files_form[] = $input;
    }
    $this
      ->assertEqual($files_query, $files_form, 'Files are sorted in the form the same as they are in the query.');
  }

  /**
   * Tests files overview with different user permissions.
   */
  function testFilesAdminPages() {
    $this
      ->drupalLogin($this->admin_user);
    $files['public_image'] = $this
      ->createFileEntity(array(
      'scheme' => 'public',
      'uid' => $this->base_user_1->uid,
      'type' => 'image',
    ));
    $files['public_document'] = $this
      ->createFileEntity(array(
      'scheme' => 'public',
      'uid' => $this->base_user_2->uid,
      'type' => 'document',
    ));
    $files['private_image'] = $this
      ->createFileEntity(array(
      'scheme' => 'private',
      'uid' => $this->base_user_1->uid,
      'type' => 'image',
    ));
    $files['private_document'] = $this
      ->createFileEntity(array(
      'scheme' => 'private',
      'uid' => $this->base_user_2->uid,
      'type' => 'document',
    ));

    // Verify view, usage, edit, and delete links for any file.
    $this
      ->drupalGet('admin/content/file');
    $this
      ->assertResponse(200);
    foreach ($files as $file) {
      $this
        ->assertLinkByHref('file/' . $file->fid);
      $this
        ->assertLinkByHref('file/' . $file->fid . '/usage');
      $this
        ->assertLinkByHref('file/' . $file->fid . '/edit');
      $this
        ->assertLinkByHref('file/' . $file->fid . '/delete');

      // Verify tableselect.
      $this
        ->assertFieldByName('files[' . $file->fid . ']', '', t('Tableselect found.'));
    }

    // Verify no operation links are displayed for regular users.
    $this
      ->drupalLogout();
    $this
      ->drupalLogin($this->base_user_1);
    $this
      ->drupalGet('admin/content/file');
    $this
      ->assertResponse(200);
    $this
      ->assertLinkByHref('file/' . $files['public_image']->fid);
    $this
      ->assertLinkByHref('file/' . $files['public_document']->fid);
    $this
      ->assertNoLinkByHref('file/' . $files['public_image']->fid . '/edit');
    $this
      ->assertNoLinkByHref('file/' . $files['public_image']->fid . '/delete');
    $this
      ->assertNoLinkByHref('file/' . $files['public_document']->fid . '/edit');
    $this
      ->assertNoLinkByHref('file/' . $files['public_document']->fid . '/delete');

    // Verify no tableselect.
    $this
      ->assertNoFieldByName('files[' . $files['public_image']->fid . ']', '', t('No tableselect found.'));

    // Verify private file is displayed with permission.
    $this
      ->drupalLogout();
    $this
      ->drupalLogin($this->base_user_2);
    $this
      ->drupalGet('admin/content/file');
    $this
      ->assertResponse(200);
    $this
      ->assertLinkByHref('file/' . $files['private_document']->fid);

    // Verify no operation links are displayed.
    $this
      ->assertNoLinkByHref('file/' . $files['private_document']->fid . '/edit');
    $this
      ->assertNoLinkByHref('file/' . $files['private_document']->fid . '/delete');

    // Verify user cannot see private file of other users.
    $this
      ->assertNoLinkByHref('file/' . $files['private_image']->fid);
    $this
      ->assertNoLinkByHref('file/' . $files['private_image']->fid . '/edit');
    $this
      ->assertNoLinkByHref('file/' . $files['private_image']->fid . '/delete');

    // Verify no tableselect.
    $this
      ->assertNoFieldByName('files[' . $files['private_document']->fid . ']', '', t('No tableselect found.'));

    // Verify private file is displayed with permission.
    $this
      ->drupalLogout();
    $this
      ->drupalLogin($this->base_user_3);
    $this
      ->drupalGet('admin/content/file');
    $this
      ->assertResponse(200);

    // Verify user can see private file of other users.
    $this
      ->assertLinkByHref('file/' . $files['private_document']->fid);
    $this
      ->assertLinkByHref('file/' . $files['private_image']->fid);

    // Verify operation links are displayed for users with appropriate permission.
    $this
      ->drupalLogout();
    $this
      ->drupalLogin($this->base_user_4);
    $this
      ->drupalGet('admin/content/file');
    $this
      ->assertResponse(200);
    foreach ($files as $file) {
      $this
        ->assertLinkByHref('file/' . $file->fid);
      $this
        ->assertLinkByHref('file/' . $file->fid . '/usage');
      $this
        ->assertLinkByHref('file/' . $file->fid . '/edit');
      $this
        ->assertLinkByHref('file/' . $file->fid . '/delete');
    }

    // Verify file access can be bypassed.
    $this
      ->drupalLogout();
    $this
      ->drupalLogin($this->admin_user);
    $this
      ->drupalGet('admin/content/file');
    $this
      ->assertResponse(200);
    foreach ($files as $file) {
      $this
        ->assertLinkByHref('file/' . $file->fid);
      $this
        ->assertLinkByHref('file/' . $file->fid . '/usage');
      $this
        ->assertLinkByHref('file/' . $file->fid . '/edit');
      $this
        ->assertLinkByHref('file/' . $file->fid . '/delete');
    }
  }

}

/**
 * Tests the file usage page.
 */
class FileEntityUsageTestCase extends FileEntityTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'File entity usage',
      'description' => 'Create a file and verify its usage.',
      'group' => 'File entity',
    );
  }
  function setUp() {
    parent::setUp();
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
      'bypass file access',
      'edit own article content',
    ));
    $this
      ->drupalLogin($web_user);
  }

  /**
   * Create a file and verify its usage information.
   */
  function testFileEntityUsagePage() {
    $image_field = 'field_image';
    $image = $this
      ->getTestFile('image');

    // Create a node, save it, then edit it to upload a file.
    $edit = array(
      "files[" . $image_field . "_" . LANGUAGE_NONE . "_0]" => drupal_realpath($image->uri),
    );
    $node = $this
      ->drupalCreateNode(array(
      'type' => 'article',
    ));
    $this
      ->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));

    // Load the uploaded file.
    $fid = $this
      ->getLastFileId();
    $file = file_load($fid);

    // View the file's usage page.
    $this
      ->drupalGet('file/' . $file->fid . '/usage');

    // Verify that a link to the entity is available.
    $this
      ->assertLink($node->title);
    $this
      ->assertLinkByHref('node/' . $node->nid);

    // Verify that the entity type and use count information is also present.
    $expected_values = array(
      'type' => 'node',
      'count' => 1,
    );
    foreach ($expected_values as $name => $value) {
      $this
        ->assertTrue($this
        ->xpath('//table/tbody/tr/td[normalize-space(text())=:text]', array(
        ':text' => $value,
      )), t('File usage @name was found in the table.', array(
        '@name' => $name,
      )));
    }

    // Add a reference to the file from the same entity but registered by a
    // different module to ensure that the usage count is incremented and no
    // additional table rows are created.
    file_usage_add($file, 'example_module', 'node', $node->nid, 2);

    // Reload the page and verify that the expected values are present.
    $this
      ->drupalGet('file/' . $file->fid . '/usage');
    $expected_values['count'] = 3;
    foreach ($expected_values as $name => $value) {
      $this
        ->assertTrue($this
        ->xpath('//table/tbody/tr/td[normalize-space(text())=:text]', array(
        ':text' => $value,
      )), t('File usage @name was found in the table.', array(
        '@name' => $name,
      )));
    }

    // Add a reference to the file from an entity that doesn't exist to ensure
    // that this case is handled.
    file_usage_add($file, 'test_module', 'imaginary', 1);

    // Reload the page.
    $this
      ->drupalGet('file/' . $file->fid . '/usage');

    // Verify that the module name is used in place of a link to the entity.
    $this
      ->assertNoLink('test_module');
    $this
      ->assertRaw('(entity not loaded)', '"(entity not loaded)" notice used in place of link to the entity.');

    // Verify that the entity type and use count information is also present.
    $expected_values = array(
      'type' => 'imaginary',
      'count' => 1,
    );
    foreach ($expected_values as $name => $value) {
      $this
        ->assertTrue($this
        ->xpath('//table/tbody/tr/td[normalize-space(text())=:text]', array(
        ':text' => $value,
      )), t('File usage @name was found in the table.', array(
        '@name' => $name,
      )));
    }
  }

}

/**
 * Tests image alt and title text.
 */
class FileEntityAltTitleTestCase extends FileEntityTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'File entity alt and title text',
      'description' => 'Create an image file with alt and title text.',
      'group' => 'File entity',
      'dependencies' => array(
        'token',
      ),
    );
  }
  function setUp() {
    parent::setUp('token');
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
      'edit own image files',
    ));
    $this
      ->drupalLogin($web_user);
  }

  /**
   * Create an "image" file and verify its associated alt and title text.
   */
  function testFileEntityAltTitle() {
    $test_file = $this
      ->getTestFile('image');
    $alt_field_name = 'field_file_image_alt_text';

    // Name of the default alt text field added to the image file type.
    $title_field_name = 'field_file_image_title_text';

    // Name of the default title text field added to the image file type.
    // Create a file.
    $edit = array();
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
    $this
      ->drupalPost('file/add', $edit, t('Next'));

    // Step 2: Scheme selection.
    if ($this
      ->xpath('//input[@name="scheme"]')) {
      $this
        ->drupalPost(NULL, array(), t('Next'));
    }

    // Step 3: Attached fields.
    $alt = 'Quote&quot; Amp&amp; ' . 'Файл для тестирования ' . $this
      ->randomName();

    // Generate alt text containing HTML entities, spaces and non-latin characters.
    $title = 'Quote&quot; Amp&amp; ' . 'Файл для тестирования ' . $this
      ->randomName();

    // Generate title text containing HTML entities, spaces and non-latin characters.
    $edit = array();
    $edit[$alt_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $alt;
    $edit[$title_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $title;
    $this
      ->drupalPost(NULL, $edit, t('Save'));

    // Check that the image file has been uploaded.
    $this
      ->assertRaw(t('!type %name was uploaded.', array(
      '!type' => 'Image',
      '%name' => $test_file->filename,
    )), t('Image file uploaded.'));

    // Check that the file exists in the database.
    $file = $this
      ->getFileByFilename($test_file->filename);
    $this
      ->assertTrue($file, t('File found in database.'));

    // Check that the alt and title text was loaded from the fields.
    $this
      ->assertEqual($file->alt, $alt, t('Alt text was stored as file metadata.'));
    $this
      ->assertEqual($file->title, $title, t('Title text was stored as file metadata.'));

    // Verify that the alt and title text is present on the page.
    $image_info = array(
      'path' => $file->uri,
      'alt' => $alt,
      'title' => $title,
      'width' => $file->width,
      'height' => $file->height,
    );
    $default_output = theme('image', $image_info);
    $this
      ->assertRaw($default_output, 'Image displayed using user supplied alt and title attributes.');

    // Verify that the alt and title text can be edited.
    $new_alt = $this
      ->randomName();
    $new_title = $this
      ->randomName();
    $edit = array();
    $edit[$alt_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $new_alt;
    $edit[$title_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $new_title;
    $this
      ->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
    $image_info = array(
      'path' => $file->uri,
      'alt' => $new_alt,
      'title' => $new_title,
      'width' => $file->width,
      'height' => $file->height,
    );
    $default_output = theme('image', $image_info);
    $this
      ->assertRaw($default_output, 'Image displayed using updated alt and title attributes.');
  }

}

/**
 * Test changing the scheme of a file.
 */
class FileEntityChangeSchemeTestCase extends FileEntityTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'Changing file scheme',
      'description' => 'Test changing the scheme of a file.',
      'group' => 'File entity',
    );
  }
  function testChangeScheme() {

    // Select the first text test file to use.
    $file = $this
      ->createFileEntity(array(
      'type' => 'document',
    ));
    $this
      ->assertEqual(file_uri_scheme($file->uri), 'public', 'File is public.');

    // Create a user with file edit permissions.
    $user = $this
      ->drupalCreateUser(array(
      'edit any document files',
    ));
    $this
      ->drupalLogin($user);
    $this
      ->drupalGet('file/' . $file->fid . '/edit');
    $this
      ->assertNoFieldByName('scheme');

    // Create a user with file admin permissions.
    $user = $this
      ->drupalCreateUser(array(
      'edit any document files',
      'administer files',
    ));
    $this
      ->drupalLogin($user);
    $this
      ->drupalGet('file/' . $file->fid . '/edit');
    $this
      ->assertFieldByName('scheme', 'public');
    $this
      ->drupalPost(NULL, array(
      'scheme' => 'private',
    ), 'Save');
    $file = entity_load_unchanged('file', $file->fid);
    $this
      ->assertEqual(file_uri_scheme($file->uri), 'private', 'File has changed to private.');
  }

}

/**
 * Tests replacing the file associated with a file entity.
 */
class FileEntityReplaceTestCase extends FileEntityTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'File replacement',
      'description' => 'Test file replace functionality.',
      'group' => 'File entity',
    );
  }
  function setUp() {
    parent::setUp();
  }

  /**
   * @todo Test image dimensions for an image field are reset when a file is replaced.
   * @todo Test image styles are cleared when an image is updated.
   */
  function testReplaceFile() {

    // Select the first text test file to use.
    $file = $this
      ->createFileEntity(array(
      'type' => 'document',
    ));

    // Create a user with file edit permissions.
    $user = $this
      ->drupalCreateUser(array(
      'edit any document files',
    ));
    $this
      ->drupalLogin($user);

    // Test that the Upload widget appears for a local file.
    $this
      ->drupalGet('file/' . $file->fid . '/edit');
    $this
      ->assertFieldByName('files[replace_upload]');

    // Test that file saves without uploading a file.
    $this
      ->drupalPost(NULL, array(), t('Save'));
    $this
      ->assertText(t('Document @file has been updated.', array(
      '@file' => $file->filename,
    )), 'File was updated without file upload.');

    // Get a text file to use as a replacement.
    $original = clone $file;
    $replacement = $this
      ->getTestFile('text');

    // Test that the file saves when uploading a replacement file.
    $edit = array();
    $edit['files[replace_upload]'] = drupal_realpath($replacement->uri);
    $this
      ->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
    $this
      ->assertText(t('Document @file has been updated.', array(
      '@file' => $file->filename,
    )), 'File was updated with file upload.');

    // Re-load the file from the database.
    $file = file_load($file->fid);

    // Test how file properties changed after the file has been replaced.
    $this
      ->assertEqual($file->filename, $original->filename, 'Updated file name did not change.');
    $this
      ->assertNotEqual($file->filesize, $original->filesize, 'Updated file size changed from previous file.');
    $this
      ->assertEqual($file->filesize, $replacement->filesize, 'Updated file size matches uploaded file.');
    $this
      ->assertEqual(file_get_contents($file->uri), file_get_contents($replacement->uri), 'Updated file contents matches uploaded file.');
    $this
      ->assertFalse(entity_load('file', FALSE, array(
      'status' => 0,
    )), 'Temporary file used for replacement was deleted.');

    // Get an image file.
    $image = $this
      ->getTestFile('image');
    $edit['files[replace_upload]'] = drupal_realpath($image->uri);

    // Test that validation works by uploading a non-text file as a replacement.
    $this
      ->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
    $this
      ->assertRaw(t('The specified file %file could not be uploaded. Only files with the following extensions are allowed:', array(
      '%file' => $image->filename,
    )), 'File validation works, upload failed correctly.');

    // Create a non-local file record.
    $file2 = new stdClass();
    $file2->uri = 'oembed://' . $this
      ->randomName();
    $file2->filename = drupal_basename($file2->uri);
    $file2->filemime = 'image/oembed';
    $file2->type = 'image';
    $file2->uid = 1;
    $file2->timestamp = REQUEST_TIME;
    $file2->filesize = 0;
    $file2->status = 0;

    // Write the record directly rather than calling file_save() so we don't
    // invoke the hooks.
    $this
      ->assertTrue(drupal_write_record('file_managed', $file2), 'Non-local file was added to the database.');

    // Test that Upload widget does not appear for non-local file.
    $this
      ->drupalGet('file/' . $file2->fid . '/edit');
    $this
      ->assertNoFieldByName('files[replace_upload]');
  }

}

/**
 * Tests file entity tokens.
 */
class FileEntityTokenTestCase extends FileEntityTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'File entity tokens',
      'description' => 'Test the file entity tokens.',
      'group' => 'File entity',
    );
  }
  function setUp() {
    parent::setUp();
  }
  function testFileEntityTokens() {
    $file = $this
      ->createFileEntity(array(
      'type' => 'document',
    ));
    $tokens = array(
      'type' => 'Document',
      'type:name' => 'Document',
      'type:machine-name' => 'document',
      'type:count' => 1,
    );
    $this
      ->assertTokens('file', array(
      'file' => $file,
    ), $tokens);
    $file = $this
      ->createFileEntity(array(
      'type' => 'image',
    ));
    $tokens = array(
      'type' => 'Image',
      'type:name' => 'Image',
      'type:machine-name' => 'image',
      'type:count' => 1,
    );
    $this
      ->assertTokens('file', array(
      'file' => $file,
    ), $tokens);
  }
  function assertTokens($type, array $data, array $tokens, array $options = array()) {
    $token_input = drupal_map_assoc(array_keys($tokens));
    $values = token_generate($type, $token_input, $data, $options);
    foreach ($tokens as $token => $expected) {
      if (!isset($expected)) {
        $this
          ->assertTrue(!isset($values[$token]), t("Token value for [@type:@token] was not generated.", array(
          '@type' => $type,
          '@token' => $token,
        )));
      }
      elseif (!isset($values[$token])) {
        $this
          ->fail(t("Token value for [@type:@token] was not generated.", array(
          '@type' => $type,
          '@token' => $token,
        )));
      }
      elseif (!empty($options['regex'])) {
        $this
          ->assertTrue(preg_match('/^' . $expected . '$/', $values[$token]), t("Token value for [@type:@token] was '@actual', matching regular expression pattern '@expected'.", array(
          '@type' => $type,
          '@token' => $token,
          '@actual' => $values[$token],
          '@expected' => $expected,
        )));
      }
      else {
        $this
          ->assertIdentical($values[$token], $expected, t("Token value for [@type:@token] was '@actual', expected value '@expected'.", array(
          '@type' => $type,
          '@token' => $token,
          '@actual' => $values[$token],
          '@expected' => $expected,
        )));
      }
    }
    return $values;
  }

}

/**
 * Tests adding support for bundles to the core 'file' entity.
 */
class FileEntityTypeTestCase extends FileEntityTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'File entity types',
      'description' => 'Test the file entity types.',
      'group' => 'File entity',
    );
  }
  function setUp() {
    parent::setUp();
  }

  /**
   * Test admin pages access and functionality.
   */
  function testAdminPages() {

    // Create a user with file type administration access.
    $user = $this
      ->drupalCreateUser(array(
      'administer file types',
    ));
    $this
      ->drupalLogin($user);
    $this
      ->drupalGet('admin/structure/file-types');
    $this
      ->assertResponse(200, 'File types admin page is accessible');
  }

  /**
   * Test creating a new type. Basic CRUD.
   */
  function testCreate() {
    $type_machine_type = 'foo';
    $type_machine_label = 'foobar';
    $type = $this
      ->createFileType(array(
      'type' => $type_machine_type,
      'label' => $type_machine_label,
    ));
    $loaded_type = file_type_load($type_machine_type);
    $this
      ->assertEqual($loaded_type->label, $type_machine_label, "Was able to create a type and retrieve it.");
  }

  /**
   * Test file types CRUD UI.
   */
  function testTypesCrudUi() {
    $this
      ->drupalGet('admin/structure/file-types');
    $this
      ->assertResponse(403, 'File types UI page is not accessible to unauthorized users.');
    $user = $this
      ->drupalCreateUser(array(
      'administer file types',
      'administer fields',
    ));
    $this
      ->drupalLogin($user);
    $this
      ->drupalGet('admin/structure/file-types');
    $this
      ->assertResponse(200, 'File types UI page is accessible to users with adequate permission.');

    // Create new file type.
    $edit = array(
      'label' => t('Test type'),
      'type' => 'test_type',
      'description' => t('This is dummy file type used just for testing.'),
      'mimetypes' => 'image/png',
    );
    $this
      ->drupalGet('admin/structure/file-types/add');
    $this
      ->drupalPost(NULL, $edit, t('Save'));
    $this
      ->assertText(t('The file type @type has been updated.', array(
      '@type' => $edit['label'],
    )), 'New file type successfully created.');
    $this
      ->assertText($edit['label'], 'New file type created: label found.');
    $this
      ->assertText($edit['description'], 'New file type created: description found.');
    $this
      ->assertFieldByXPath("//table//tr[1]//td[7]", t('Normal'), 'Newly created file type is stored in DB.');
    $this
      ->assertLink(t('disable'), 0, 'Able to disable newly created file type.');
    $this
      ->assertLink(t('delete'), 0, 'Able to delete newly created file type.');
    $this
      ->assertLinkByHref('admin/structure/file-types/manage/' . $edit['type'] . '/disable', 0, 'Disable link points to disable confirmation page.');
    $this
      ->assertLinkByHref('admin/structure/file-types/manage/' . $edit['type'] . '/delete', 0, 'Delete link points to delete confirmation page.');

    // Edit file type.
    $this
      ->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/edit');
    $this
      ->assertRaw(t('Save'), 'Save button found on edit page.');
    $this
      ->assertRaw(t('Delete'), 'Delete button found on edit page.');
    $this
      ->assertRaw($edit['label'], 'Label found on file type edit page');
    $this
      ->assertText($edit['description'], 'Description found on file type edit page');
    $this
      ->assertText($edit['mimetypes'], 'Mime-type configuration found on file type edit page');
    $this
      ->assertText(t('Mimetype List'), 'Mimetype list present on edit form.');

    // Modify file type.
    $edit['label'] = t('New type label');
    $this
      ->drupalPost(NULL, array(
      'label' => $edit['label'],
    ), t('Save'));
    $this
      ->assertText(t('The file type @type has been updated.', array(
      '@type' => $edit['label'],
    )), 'File type was modified.');
    $this
      ->assertText($edit['label'], 'Modified label found on file types list.');

    // Disable and re-enable file type.
    $this
      ->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/disable');
    $this
      ->assertText(t('Are you sure you want to disable the file type @type?', array(
      '@type' => $edit['label'],
    )), 'Disable confirmation page found.');
    $this
      ->drupalPost(NULL, array(), t('Disable'));
    $this
      ->assertText(t('The file type @type has been disabled.', array(
      '@type' => $edit['label'],
    )), 'Disable confirmation message found.');
    $this
      ->assertFieldByXPath("//table//tr[5]//td[1]", $edit['label'], 'Disabled type moved to the tail of the list.');
    $this
      ->assertLink(t('enable'), 0, 'Able to re-enable newly created file type.');
    $this
      ->assertLinkByHref('admin/structure/file-types/manage/' . $edit['type'] . '/enable', 0, 'Enable link points to enable confirmation page.');
    $this
      ->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/enable');
    $this
      ->assertText(t('Are you sure you want to enable the file type @type?', array(
      '@type' => $edit['label'],
    )), 'Enable confirmation page found.');
    $this
      ->drupalPost(NULL, array(), t('Enable'));
    $this
      ->assertText(t('The file type @type has been enabled.', array(
      '@type' => $edit['label'],
    )), 'Enable confirmation message found.');
    $this
      ->assertFieldByXPath("//table//tr[1]//td[1]", $edit['label'], 'Enabled type moved to the top of the list.');

    // Delete newly created type.
    $this
      ->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/delete');
    $this
      ->assertText(t('Are you sure you want to delete the file type @type?', array(
      '@type' => $edit['label'],
    )), 'Delete confirmation page found.');
    $this
      ->drupalPost(NULL, array(), t('Delete'));
    $this
      ->assertText(t('The file type @type has been deleted.', array(
      '@type' => $edit['label'],
    )), 'Delete confirmation message found.');
    $this
      ->drupalGet('admin/structure/file-types');
    $this
      ->assertNoText($edit['label'], 'File type successfully deleted.');

    // Edit exported file type.
    $this
      ->drupalGet('admin/structure/file-types/manage/image/edit');
    $this
      ->assertRaw(t('Image'), 'Label found on file type edit page');
    $this
      ->assertText("image/*", 'Mime-type configuration found on file type edit page');
    $this
      ->drupalPost(NULL, array(
      'label' => t('Funky images'),
    ), t('Save'));
    $this
      ->assertText(t('The file type @type has been updated.', array(
      '@type' => t('Funky images'),
    )), 'File type was modified.');
    $this
      ->assertText(t('Funky image'), 'Modified label found on file types list.');
    $this
      ->assertFieldByXPath("//table//tr[1]//td[7]", t('Overridden'), 'Modified type overrides configuration from code.');
    $this
      ->assertLink(t('revert'), 0, 'Able to revert overridden file type.');
    $this
      ->assertLinkByHref('admin/structure/file-types/manage/image/revert', 0, 'Revert link points to revert confirmation page.');

    // Revert file type.
    $this
      ->drupalGet('admin/structure/file-types/manage/image/revert');
    $this
      ->assertText(t('Are you sure you want to revert the file type @type?', array(
      '@type' => t('Funky images'),
    )), 'Revert confirmation page found.');
    $this
      ->drupalPost(NULL, array(), t('Revert'));
    $this
      ->assertText(t('The file type @type has been reverted.', array(
      '@type' => t('Funky images'),
    )), 'Revert confirmation message found.');
    $this
      ->assertText(t('Image'), 'Reverted file type found in list.');
    $this
      ->assertFieldByXPath("//table//tr[1]//td[7]", t('Default'), 'Reverted file type shows correct state.');
  }

}

/**
 * Tests the file entity access API.
 */
class FileEntityAccessTestCase extends FileEntityTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'File entity access',
      'description' => 'Test the access aspects of file entity.',
      'group' => 'File entity',
    );
  }
  function setUp() {
    parent::setUp();

    // Remove the "view files" permission which is set by default for all users
    // so we can test this permission correctly.
    $roles = user_roles();
    foreach ($roles as $rid => $role) {
      user_role_revoke_permissions($rid, array(
        'view files',
      ));
    }
  }

  /**
   * Runs basic tests for file_entity_access function.
   */
  function testFileEntityAccess() {
    $file = $this
      ->createFileEntity(array(
      'type' => 'image',
    ));

    // Ensures user with 'bypass file access' permission can do everything.
    $web_user = $this
      ->drupalCreateUser(array(
      'bypass file access',
    ));
    $this
      ->assertFileEntityAccess(array(
      'create' => TRUE,
    ), NULL, $web_user);
    $this
      ->assertFileEntityAccess(array(
      'view' => TRUE,
      'download' => TRUE,
      'update' => TRUE,
      'delete' => TRUE,
    ), $file, $web_user);

    // A user with 'administer files' should not access CRUD operations.
    $web_user = $this
      ->drupalCreateUser(array(
      'administer files',
    ));
    $this
      ->assertFileEntityAccess(array(
      'view' => FALSE,
      'download' => FALSE,
      'update' => FALSE,
      'delete' => FALSE,
    ), $file, $web_user);

    // User cannot 'view files'.
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
    ));
    $this
      ->assertFileEntityAccess(array(
      'view' => FALSE,
    ), $file, $web_user);

    // But can upload new ones.
    $this
      ->assertFileEntityAccess(array(
      'create' => TRUE,
    ), NULL, $web_user);

    // User can view own files but no other files.
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
      'view own files',
    ));
    $this
      ->assertFileEntityAccess(array(
      'view' => FALSE,
    ), $file, $web_user);
    $file->uid = $web_user->uid;
    $this
      ->assertFileEntityAccess(array(
      'view' => TRUE,
    ), $file, $web_user);

    // User can download own files but no other files.
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
      'download own image files',
    ));
    $this
      ->assertFileEntityAccess(array(
      'download' => FALSE,
    ), $file, $web_user);
    $file->uid = $web_user->uid;
    $this
      ->assertFileEntityAccess(array(
      'download' => TRUE,
    ), $file, $web_user);

    // User can update own files but no other files.
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
      'view own files',
      'edit own image files',
    ));
    $this
      ->assertFileEntityAccess(array(
      'update' => FALSE,
    ), $file, $web_user);
    $file->uid = $web_user->uid;
    $this
      ->assertFileEntityAccess(array(
      'update' => TRUE,
    ), $file, $web_user);

    // User can delete own files but no other files.
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
      'view own files',
      'edit own image files',
      'delete own image files',
    ));
    $this
      ->assertFileEntityAccess(array(
      'delete' => FALSE,
    ), $file, $web_user);
    $file->uid = $web_user->uid;
    $this
      ->assertFileEntityAccess(array(
      'delete' => TRUE,
    ), $file, $web_user);

    // User can view any file.
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
      'view files',
    ));
    $this
      ->assertFileEntityAccess(array(
      'view' => TRUE,
    ), $file, $web_user);

    // User can download any file.
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
      'download any image files',
    ));
    $this
      ->assertFileEntityAccess(array(
      'download' => TRUE,
    ), $file, $web_user);

    // User can edit any file.
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
      'view files',
      'edit any image files',
    ));
    $this
      ->assertFileEntityAccess(array(
      'update' => TRUE,
    ), $file, $web_user);

    // User can delete any file.
    $web_user = $this
      ->drupalCreateUser(array(
      'create files',
      'view files',
      'edit any image files',
      'delete any image files',
    ));
    $this
      ->assertFileEntityAccess(array(
      'delete' => TRUE,
    ), $file, $web_user);
  }

  /**
   * Tests page access.
   *
   * Verifies the privileges required to access the following pages:
   *  file/add
   *  file/%/view
   *  file/%/download
   *  file/%/edit
   *  file/%/usage
   *  file/%/delete
   */
  function testFileEntityPageAccess() {

    // Test creating files without permission.
    $web_user = $this
      ->drupalCreateUser();
    $this
      ->drupalLogin($web_user);
    $this
      ->drupalGet('file/add');
    $this
      ->assertResponse(403, 'Users without access can not access the file add page');

    // Test creating files with permission.
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
      'create files' => TRUE,
    ));
    $this
      ->drupalGet('file/add');
    $this
      ->assertResponse(200, 'Users with access can access the file add page');
    $file = $this
      ->createFileEntity(array(
      'type' => 'document',
      'uid' => $web_user->uid,
    ));

    // Test viewing own files without permission.
    $this
      ->drupalGet("file/{$file->fid}/view");
    $this
      ->assertResponse(403, 'Users without access can not view their own files');

    // Test viewing own files with permission.
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
      'view own files' => TRUE,
    ));
    $this
      ->drupalGet("file/{$file->fid}/view");
    $this
      ->assertResponse(200, 'Users with access can view their own files');

    // Test viewing any files without permission.
    $file->uid = 1;
    file_save($file);
    $this
      ->drupalGet("file/{$file->fid}/view");
    $this
      ->assertResponse(403, 'Users with access can not view any file');

    // Test viewing any files with permission.
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
      'view files' => TRUE,
    ));
    $this
      ->drupalGet("file/{$file->fid}/view");
    $this
      ->assertResponse(200, 'Users with access can view any file');

    // Test downloading own files without permission.
    $file->uid = $web_user->uid;
    file_save($file);
    $url = "file/{$file->fid}/download";
    $this
      ->drupalGet($url, array(
      'query' => array(
        'token' => file_entity_get_download_token($file),
      ),
    ));
    $this
      ->assertResponse(403, 'Users without access can not download their own files');

    // Test downloading own files with permission.
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
      'download own document files' => TRUE,
    ));
    $this
      ->drupalGet($url, array(
      'query' => array(
        'token' => file_entity_get_download_token($file),
      ),
    ));
    $this
      ->assertResponse(200, 'Users with access can download their own files');

    // Test downloading any files without permission.
    $file->uid = 1;
    file_save($file);
    $url = "file/{$file->fid}/download";
    $this
      ->drupalGet($url, array(
      'query' => array(
        'token' => file_entity_get_download_token($file),
      ),
    ));
    $this
      ->assertResponse(403, 'Users without access can not download any file');

    // Test downloading any files with permission.
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
      'download any document files' => TRUE,
    ));
    $this
      ->drupalGet($url, array(
      'query' => array(
        'token' => file_entity_get_download_token($file),
      ),
    ));
    $this
      ->assertResponse(200, 'Users with access can download any file');

    // Test downloading files with an invalid token.
    $this
      ->drupalGet($url, array(
      'query' => array(
        'token' => 'invalid-token',
      ),
    ));
    $this
      ->assertResponse(403, 'Cannot download file with an invalid token.');

    // Test downloading files without a token.
    $this
      ->drupalGet($url);
    $this
      ->assertResponse(403, 'Cannot download file without a token.');
    variable_set('file_entity_allow_insecure_download', TRUE);

    // Test downloading files with permission but without a token when insecure
    // downloads are enabled.
    $this
      ->drupalGet($url);
    $this
      ->assertResponse(200, 'Users with access can download the file without a token when file_entity_allow_insecure_download is set.');

    // Tests editing own files without permission.
    $file->uid = $web_user->uid;
    file_save($file);
    $this
      ->drupalGet("file/{$file->fid}/edit");
    $this
      ->assertResponse(403, 'Users without access can not edit own files');

    // Tests checking the usage of their own files without permission.
    $this
      ->drupalGet("file/{$file->fid}/usage");
    $this
      ->assertResponse(403, 'Users without access can not check the usage of their own files');

    // Tests editing own files with permission.
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
      'edit own document files' => TRUE,
    ));
    $this
      ->drupalGet("file/{$file->fid}/edit");
    $this
      ->assertResponse(200, 'Users with access can edit own files');

    // Tests checking the usage of their own files without permission.
    $this
      ->drupalGet("file/{$file->fid}/usage");
    $this
      ->assertResponse(200, 'Users with access can check the usage of their own files');

    // Tests editing any files without permission.
    $file->uid = 1;
    file_save($file);
    $this
      ->drupalGet("file/{$file->fid}/edit");
    $this
      ->assertResponse(403, 'Users without access can not edit any file');

    // Tests checking the usage of any files without permission.
    $this
      ->drupalGet("file/{$file->fid}/usage");
    $this
      ->assertResponse(403, 'Users without access can not check the usage of any file');

    // Tests editing any files with permission.
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
      'edit any document files' => TRUE,
    ));
    $this
      ->drupalGet("file/{$file->fid}/edit");
    $this
      ->assertResponse(200, 'Users with access can edit any file');

    // Tests checking the usage of any files with permission.
    $this
      ->drupalGet("file/{$file->fid}/usage");
    $this
      ->assertResponse(200, 'Users with access can check the usage of any file');

    // Tests deleting own files without permission.
    $file->uid = $web_user->uid;
    file_save($file);
    $this
      ->drupalGet("file/{$file->fid}/delete");
    $this
      ->assertResponse(403, 'Users without access can not delete their own files');

    // Tests deleting own files with permission.
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
      'delete own document files' => TRUE,
    ));
    $this
      ->drupalGet("file/{$file->fid}/delete");
    $this
      ->assertResponse(200, 'Users with access can delete their own files');

    // Tests deleting any files without permission.
    $file->uid = 1;
    file_save($file);
    $this
      ->drupalGet("file/{$file->fid}/delete");
    $this
      ->assertResponse(403, 'Users without access can not delete any file');

    // Tests deleting any files with permission.
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
      'delete any document files' => TRUE,
    ));
    $this
      ->drupalGet("file/{$file->fid}/delete");
    $this
      ->assertResponse(200, 'Users with access can delete any file');
  }

  /**
   * Test to see if we have access to download private files when granted the permissions.
   */
  function testFileEntityPrivateDownloadAccess() {
    foreach ($this
      ->getPrivateDownloadAccessCases() as $case) {

      // Create users and login only if non-anonymous.
      $authenticated_user = !is_null($case['permissions']);
      if ($authenticated_user) {
        $account = $this
          ->drupalCreateUser($case['permissions']);
        $this
          ->drupalLogin($account);
      }

      // Create private, permanent files owned by this user only he's an owner.
      if (!empty($case['owner'])) {
        $file = $this
          ->createFileEntity(array(
          'type' => 'document',
          'uid' => $account->uid,
          'scheme' => 'private',
        ));

        // Check if the physical file is there.
        $arguments = array(
          '%name' => $file->filename,
          '%username' => $account->name,
          '%uri' => $file->uri,
        );
        $this
          ->assertTrue(is_file($file->uri), format_string('File %name owned by %username successfully created at %uri.', $arguments));
        $url = file_create_url($file->uri);
        $message_file_info = ' ' . format_string('File %uri was checked.', array(
          '%uri' => $file->uri,
        ));
      }

      // Try to download the file.
      $this
        ->drupalGet($url);
      $this
        ->assertResponse($case['expect'], $case['message'] . $message_file_info);

      // Logout authenticated users.
      if ($authenticated_user) {
        $this
          ->drupalLogout();
      }
    }
  }

  /**
   * Asserts file_entity_access correctly grants or denies access.
   */
  function assertFileEntityAccess($ops, $file, $account) {
    drupal_static_reset('file_entity_access');
    foreach ($ops as $op => $result) {
      $msg = t("file_entity_access returns @result with operation '@op'.", array(
        '@result' => $result ? 'true' : 'false',
        '@op' => $op,
      ));
      $this
        ->assertEqual($result, file_entity_access($op, $file, $account), $msg);
    }
  }

  /**
   * Helper for testFileEntityPrivateDownloadAccess() test.
   *
   * Defines several cases for accesing private files.
   *
   * @return array
   *   Array of associative arrays, each one having the next keys:
   *   - "message" string with the assertion message.
   *   - "permissions" array of permissions or NULL for anonymous user.
   *   - "expect" expected HTTP response code.
   *   - "owner" Optional boolean indicating if the user is a file owner.
   */
  function getPrivateDownloadAccessCases() {
    return array(
      array(
        'message' => "File owners cannot download their own files unless they are granted the 'view own private files' permission.",
        'permissions' => array(),
        'expect' => 403,
        'owner' => TRUE,
      ),
      array(
        'message' => "File owners can download their own files as they have been granted the 'view own private files' permission.",
        'permissions' => array(
          'view own private files',
        ),
        'expect' => 200,
        'owner' => TRUE,
      ),
      array(
        'message' => "Anonymous users cannot download private files.",
        'permissions' => NULL,
        'expect' => 403,
      ),
      array(
        'message' => "Authenticated users cannot download each other's private files.",
        'permissions' => array(),
        'expect' => 403,
      ),
      array(
        'message' => "Users who can view public files are not able to download private files.",
        'permissions' => array(
          'view files',
        ),
        'expect' => 403,
      ),
      array(
        'message' => "Users who bypass file access can download any file.",
        'permissions' => array(
          'bypass file access',
        ),
        'expect' => 200,
      ),
    );
  }

}

/**
 * Tests overriding file attributes.
 */
class FileEntityAttributeOverrideTestCase extends FileEntityTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'File entity attribute override',
      'description' => 'Test overriding file entity attributes.',
      'group' => 'File entity',
    );
  }

  /**
   * Test to see if file attributes can be overridden.
   */
  function testFileEntityFileAttributeOverrides() {
    $overrides = array(
      'width' => 40,
      'height' => 20,
      'alt' => $this
        ->randomName(),
      'title' => $this
        ->randomName(),
    );

    // Create an image file entity for testing.
    $file = $this
      ->createFileEntity(array(
      'type' => 'image',
    ));

    // Override a variety of attributes.
    foreach ($overrides as $override => $value) {
      $file->override['attributes'][$override] = $value;
    }

    // Build just the file portion of a file entity.
    $build = file_view_file($file, 'full');

    // Verify that all of the overrides replaced the attributes.
    foreach ($overrides as $attribute => $expected_value) {
      $this
        ->assertEqual($build['#file']->{$attribute}, $expected_value, format_string('The %attribute was overridden correctly.', array(
        '%attribute' => $attribute,
      )));
    }
  }

}

Classes

Namesort descending Description
FileEntityAccessTestCase Tests the file entity access API.
FileEntityAdminTestCase Test file administration page functionality.
FileEntityAltTitleTestCase Tests image alt and title text.
FileEntityAttributeOverrideTestCase Tests overriding file attributes.
FileEntityChangeSchemeTestCase Test changing the scheme of a file.
FileEntityEditTestCase Tests editing existing file entities.
FileEntityFileTypeClassificationTestCase Tests file type classification functionality.
FileEntityReplaceTestCase Tests replacing the file associated with a file entity.
FileEntityTestHelper @file Test integration for the file_entity module.
FileEntityTokenTestCase Tests file entity tokens.
FileEntityTypeTestCase Tests adding support for bundles to the core 'file' entity.
FileEntityUnitTestCase Tests basic file entity functionality.
FileEntityUploadWizardTestCase Tests creating new file entities through the file upload wizard.
FileEntityUsageTestCase Tests the file usage page.