You are here

VideoField.test in Video 7.2

Tests for the the Video field type

File

tests/VideoField.test
View source
<?php

/**
 * @file
 * Tests for the the Video field type
 */

/**
 * Tests for the the Video field type
 *
 * @todo Test node revisions
 */
class VideoFieldTestCase extends DrupalWebTestCase {
  private $user;
  public static function getInfo() {
    return array(
      'name' => 'Video Field tests',
      'description' => 'Tests for the the Video field type',
      'group' => 'Video',
    );
  }
  function setUp() {
    parent::setUp(array(
      'video',
      'node',
      'locale',
    ));

    // Build test entity type
    field_create_field(array(
      'field_name' => 'videofield',
      'type' => 'video',
      'settings' => array(
        'autoconversion' => 1,
      ),
    ));
    field_create_instance(array(
      'field_name' => 'videofield',
      'entity_type' => 'node',
      'bundle' => 'page',
    ));

    // Test items
    $this->user = $this
      ->drupalCreateUser();
  }

  /**
   * Tests basic behavior for saving a new video and adding it to a node.
   */
  public function testSaveVideoFieldItem() {

    // Build test data
    $file = $this
      ->createFile();
    $node = new stdClass();
    $node->uid = $this->user->uid;
    $node->type = 'page';
    $node->title = 'Test node';
    $node->videofield['und'][0] = array(
      'fid' => $file->fid,
      'dimensions' => '100x60',
    );
    node_save($node);
    $node = node_load($node->nid);

    // Check file status set to permanent
    $file = file_load($file->fid);
    $this
      ->assertEqual(FILE_STATUS_PERMANENT, $file->status, 'The file should be permanent');
    $this
      ->assertTrue(file_exists($file->uri), 'The file should exist');

    // Check queue result
    $queues = $this
      ->getQueues($file->fid);
    $this
      ->assertEqual(1, count($queues), 'One video_queue entry should be present');
    $queue = array_shift($queues);
    $this
      ->assertEqual($file->fid, $queue->fid, 'video_queue entry should have fid ' . $file->fid);
    $this
      ->assertEqual('node', $queue->entity_type, 'video_queue entry should entity_type node');
    $this
      ->assertEqual($node->nid, $queue->entity_id, 'video_queue entry should entity_id ' . $node->nid);
    $this
      ->assertEqual(VIDEO_RENDERING_PENDING, $queue->status, 'video_queue entry should have status ' . VIDEO_RENDERING_PENDING);
    $this
      ->assertEqual('100x60', $queue->dimensions, 'video_queue entry should have dimensions 100x60');
    $this
      ->assertNull($queue->duration, 'video_queue entry should have empty duration');
    $this
      ->assertEqual(0, $queue->started, 'video_queue entry should have started 0');
    $this
      ->assertEqual(0, $queue->completed, 'video_queue entry should have completed 0');
    $this
      ->assertEqual('videofield', $queue->data['field_name'], 'video_queue entry should have field_name videofield');
    $this
      ->assertEqual('und', $queue->data['langcode'], 'video_queue entry should have langcode und');
    $this
      ->assertEqual(0, $queue->data['delta'], 'video_queue entry should have delta 0');

    // No converted files and thumbnails at this point
    $this
      ->assertEqual(0, count($this
      ->getConvertedFiles($file->fid)), 'There should be no converted files immediately after saving');
    $this
      ->assertEqual(0, count($this
      ->getThumbnailFiles($file->fid)), 'There should be no thumbnail files immediately after saving');

    // Transcode the video
    $this
      ->transcodeVideo($node, $queue->vid, $file->fid);

    // Test the transcoded video
    $queues = $this
      ->getQueues($file->fid);
    $this
      ->assertEqual(1, count($queues), 'One video_queue entry should be present');
    $queue = array_shift($queues);
    $this
      ->assertEqual(VIDEO_RENDERING_COMPLETE, $queue->status, 'video_queue entry should have status ' . VIDEO_RENDERING_COMPLETE);

    // One converted video
    $conv = $this
      ->getConvertedFiles($file->fid);
    $this
      ->assertEqual(1, count($conv), 'There should be one converted files after transcoding');

    // Five thumbnails files
    $tn = $this
      ->getThumbnailFiles($file->fid);
    $this
      ->assertEqual(5, count($tn), 'There should be five thumbnail files after transcoding');

    // One usage entry for the video
    $u = $this
      ->getFileUsage($file->fid);
    $this
      ->assertEqual(1, count($u), 'There should be one usage entry immediately after saving');
    $this
      ->assertEqual($file->fid, $u[0]->fid, 'usage entry should have fid ' . $file->fid);
    $this
      ->assertEqual('file', $u[0]->module, 'usage entry should have module file');
    $this
      ->assertEqual('node', $u[0]->type, 'usage entry should have type node');
    $this
      ->assertEqual($node->nid, $u[0]->id, 'usage entry should have id ' . $node->nid);
    $this
      ->assertEqual(1, $u[0]->count, 'usage entry should have count 1');

    // Check usage for converted video and thumbnails
    foreach ($conv + $tn as $df) {
      $u = $this
        ->getFileUsage($df->fid);
      $this
        ->assertEqual(1, count($u), 'There should be one usage entry for derived file ' . $df->fid . ' immediately after saving');
      if (count($u) == 0) {
        continue;
      }
      $this
        ->assertEqual('node', $u[0]->type, 'usage entry for derived file ' . $df->fid . ' should have type node');
      $this
        ->assertEqual($node->nid, $u[0]->id, 'usage entry for derived file ' . $df->fid . ' should have id ' . $node->nid);
    }
  }

  /**
   * Tests basic behavior for deleting a video from a node
   */
  public function testDeleteVideoFieldItem() {

    // Build test data
    $file = $this
      ->createFile('file1.mp4');
    $node = new stdClass();
    $node->uid = $this->user->uid;
    $node->type = 'page';
    $node->title = 'Test node';
    $node->videofield['und'][0] = array(
      'fid' => $file->fid,
      'dimensions' => '100x60',
    );
    node_save($node);
    $node = node_load($node->nid);

    // Quick sanity checks
    $queues = $this
      ->getQueues($file->fid);
    $this
      ->assertEqual(1, count($queues), 'One video_queue entry should be present');
    $this
      ->assertEqual(1, count($this
      ->getFileUsage($file->fid)), 'There should be one usage entry immediately after saving');
    $this
      ->transcodeVideo($node, $queues[0]->vid, $file->fid);
    $tn = $this
      ->getThumbnailFiles($file->fid);
    $conv = $this
      ->getConvertedFiles($file->fid);

    // Delete the file
    unset($node->videofield['und'][0]);
    node_save($node);

    // Check if everything is deleted properly
    $this
      ->assertEqual(0, count($this
      ->getQueues($file->fid)), 'video_queue entry should be removed');
    $this
      ->assertEqual(0, count($this
      ->getFileUsage($file->fid)), 'There should be no usage entries after deleting');
    $this
      ->assertEqual(0, count($this
      ->getThumbnailFiles($file->fid)), 'There should be no thumbnail entries after deleting');
    $this
      ->assertEqual(0, count($this
      ->getConvertedFiles($file->fid)), 'There should be no converted entries after deleting');

    // Check usage for converted video and thumbnails
    foreach ($conv + $tn as $df) {
      $u = $this
        ->getFileUsage($df->fid);
      $this
        ->assertEqual(0, count($u), 'There should be no usage entries for derived file ' . $df->fid . ' immediately after saving');
    }
  }

  /**
   * Tests saving a new video and adding it to two different nodes
   */
  public function testSaveVideoFieldItemTwice() {

    // Build test data
    $file = $this
      ->createFile('file2.mp4');
    $node1 = new stdClass();
    $node1->uid = $this->user->uid;
    $node1->type = 'page';
    $node1->title = 'Test node';
    $node1->videofield['und'][0] = array(
      'fid' => $file->fid,
      'dimensions' => '100x60',
    );
    node_save($node1);
    $node2 = new stdClass();
    $node2->uid = $this->user->uid;
    $node2->type = 'page';
    $node2->title = 'Test node';
    $node2->videofield['und'][0] = array(
      'fid' => $file->fid,
      'dimensions' => '100x60',
    );
    node_save($node2);

    // Check queue result
    $queues = $this
      ->getQueues($file->fid);
    $this
      ->assertEqual(1, count($queues), 'One video_queue entry should be present');
    $queue = array_shift($queues);
    $node1 = node_load($node1->nid);
    $this
      ->transcodeVideo($node1, $queue->vid, $file->fid);
    $node2 = node_load($node2->nid);

    // @todo the video module should not reference the entity itself because one fid can be associated with multiple entities
    $this
      ->assertEqual($node1->nid, $queue->entity_id, 'video_queue entry should entity_id ' . $node1->nid);

    // Two usage entries for the video
    $u = $this
      ->getFileUsage($file->fid);
    $this
      ->assertEqual(2, count($u), 'There should be two usage entries immediately after saving');

    // First usage row
    $this
      ->assertEqual($file->fid, $u[0]->fid, 'usage entry should have fid ' . $file->fid);
    $this
      ->assertEqual('file', $u[0]->module, 'usage entry should have module file');
    $this
      ->assertEqual('node', $u[0]->type, 'usage entry should have type node');
    $this
      ->assertEqual($node1->nid, $u[0]->id, 'usage entry should have id ' . $node1->nid);
    $this
      ->assertEqual(1, $u[0]->count, 'usage entry should have count 1');

    // Second usage row
    $this
      ->assertEqual($file->fid, $u[1]->fid, 'usage entry should have fid ' . $file->fid);
    $this
      ->assertEqual('file', $u[1]->module, 'usage entry should have module file');
    $this
      ->assertEqual('node', $u[1]->type, 'usage entry should have type node');
    $this
      ->assertEqual($node2->nid, $u[1]->id, 'usage entry should have id ' . $node2->nid);
    $this
      ->assertEqual(1, $u[1]->count, 'usage entry should have count 1');
  }

  /**
   * Tests adding a video to two different nodes and deleting them one by one
   */
  public function testDeleteVideoFieldItemTwice() {

    // Build test data
    $file = $this
      ->createFile('file3.mp4');
    $node1 = new stdClass();
    $node1->uid = $this->user->uid;
    $node1->type = 'page';
    $node1->title = 'Test node';
    $node1->videofield['und'][0] = array(
      'fid' => $file->fid,
      'dimensions' => '100x60',
    );
    node_save($node1);
    $node2 = new stdClass();
    $node2->uid = $this->user->uid;
    $node2->type = 'page';
    $node2->title = 'Test node';
    $node2->videofield['und'][0] = array(
      'fid' => $file->fid,
      'dimensions' => '100x60',
    );
    node_save($node2);
    $node1 = node_load($node1->nid);
    $node2 = node_load($node2->nid);

    // Sanity checks
    $queues = $this
      ->getQueues($file->fid);
    $this
      ->assertEqual(1, count($queues), 'One video_queue entry should be present');
    $this
      ->assertEqual(2, count($this
      ->getFileUsage($file->fid)), 'There should be two usage entries immediately after saving');
    $queue = array_shift($queues);
    $this
      ->transcodeVideo($node1, $queue->vid, $file->fid);
    node_save($node2);

    // Check converted files and thumbnails
    $conv = $this
      ->getConvertedFiles($file->fid);
    $tn = $this
      ->getThumbnailFiles($file->fid);
    $this
      ->assertEqual(1, count($conv), 'There should be 1 converted file immediately after saving');
    $this
      ->assertEqual(5, count($tn), 'There should be 5 thumbnail files immediately after saving');

    // Check usage of derived files: 2 usages should be registered
    foreach ($conv + $tn as $df) {
      $u = $this
        ->getFileUsage($df->fid);
      $this
        ->assertEqual(2, count($u), 'There should be one usage entry for derived file ' . $df->fid . ' after saving both nodes');
      if (count($u) == 0) {
        continue;
      }
      $this
        ->assertEqual('node', $u[0]->type, 'usage entry for derived file ' . $df->fid . ' should have type node');
      $this
        ->assertEqual($node1->nid, $u[0]->id, 'usage entry for derived file ' . $df->fid . ' should have id ' . $node1->nid);
      $this
        ->assertEqual('node', $u[1]->type, 'usage entry for derived file ' . $df->fid . ' should have type node');
      $this
        ->assertEqual($node2->nid, $u[1]->id, 'usage entry for derived file ' . $df->fid . ' should have id ' . $node2->nid);
    }

    // Delete the video from node 1
    unset($node1->videofield['und'][0]);
    node_save($node1);

    // Check usage of derived files: 1 usages should be registered
    foreach ($conv + $tn as $df) {
      $u = $this
        ->getFileUsage($df->fid);
      $this
        ->assertEqual(1, count($u), 'There should be one usage entry for derived file ' . $df->fid . ' after deleting the video from one node');
      if (count($u) == 0) {
        continue;
      }
      $this
        ->assertEqual('node', $u[0]->type, 'usage entry for derived file ' . $df->fid . ' should have type node');
      $this
        ->assertEqual($node2->nid, $u[0]->id, 'usage entry for derived file ' . $df->fid . ' should have id ' . $node2->nid);
    }

    // Queue entry should still be there, one usage should remain
    $this
      ->assertEqual(1, count($this
      ->getQueues($file->fid)), 'One video_queue entry should be present after deleting the video from one node');
    $this
      ->assertEqual(1, count($this
      ->getFileUsage($file->fid)), 'There should be one usage entry remaining after deleting the video from one node');

    // Check whether the converted files and thumbnails still exist
    $this
      ->assertEqual(1, count($this
      ->getConvertedFiles($file->fid)), 'There should be 1 converted file immediately after deleting the video from one node');
    $this
      ->assertEqual(5, count($this
      ->getThumbnailFiles($file->fid)), 'There should be 5 thumbnail files immediately after deleting the video from one node');

    // Delete the video from node 2
    unset($node2->videofield['und'][0]);
    node_save($node2);

    // Check if everything is deleted properly
    $this
      ->assertEqual(0, count($this
      ->getQueues($file->fid)), 'video_queue entry should be removed');
    $this
      ->assertEqual(0, count($this
      ->getFileUsage($file->fid)), 'There should be no usage entries after deleting');
    $this
      ->assertEqual(0, count($this
      ->getThumbnailFiles($file->fid)), 'There should be no thumbnail entries after deleting');
    $this
      ->assertEqual(0, count($this
      ->getConvertedFiles($file->fid)), 'There should be no converted entries after deleting');

    // Check usage of derived files: 0 usages should be registered
    foreach ($conv + $tn as $df) {
      $u = $this
        ->getFileUsage($df->fid);
      $this
        ->assertEqual(0, count($u), 'There should be no usage entry for derived file ' . $df->fid . ' after saving both nodes');
    }
  }

  /**
   * Tests adding a video to two different nodes and deleting the nodes
   */
  public function testDeleteVideoFieldItemTwice_EntityDelete() {

    // Build test data
    $file = $this
      ->createFile('file4.mp4');
    $node1 = new stdClass();
    $node1->uid = $this->user->uid;
    $node1->type = 'page';
    $node1->title = 'Test node';
    $node1->videofield['und'][0] = array(
      'fid' => $file->fid,
      'dimensions' => '100x60',
    );
    node_save($node1);
    $node2 = new stdClass();
    $node2->uid = $this->user->uid;
    $node2->type = 'page';
    $node2->title = 'Test node';
    $node2->videofield['und'][0] = array(
      'fid' => $file->fid,
      'dimensions' => '100x60',
    );
    node_save($node2);
    $node1 = node_load($node1->nid);
    $node2 = node_load($node2->nid);

    // Sanity checks
    $queues = $this
      ->getQueues($file->fid);
    $this
      ->assertEqual(1, count($queues), 'One video_queue entry should be present');
    $this
      ->assertEqual(2, count($this
      ->getFileUsage($file->fid)), 'There should be two usage entries immediately after saving');
    $this
      ->assertTrue(file_exists($file->uri), 'The file should exist');
    $queue = array_shift($queues);
    $this
      ->transcodeVideo($node1, $queue->vid, $file->fid);
    node_save($node2);

    // Delete node 1
    node_delete($node1->nid);

    // Queue entry should still be there, one usage should remain
    $this
      ->assertEqual(1, count($this
      ->getQueues($file->fid)), 'One video_queue entry should be present after deleting one node');
    $this
      ->assertEqual(1, count($this
      ->getFileUsage($file->fid)), 'There should be one usage entry remaining after deleting one node');
    $this
      ->assertTrue(file_exists($file->uri), 'The file should exist after deleting one node');

    // Check whether the converted files and thumbnails still exist
    $this
      ->assertEqual(1, count($this
      ->getConvertedFiles($file->fid)), 'There should be 1 converted file immediately after video from one node');
    $this
      ->assertEqual(5, count($this
      ->getThumbnailFiles($file->fid)), 'There should be 5 thumbnail files immediately after video from one node');

    // Delete node 2
    node_delete($node2->nid);

    // Queue entry and usage entry should still be removed
    $this
      ->assertEqual(0, count($this
      ->getQueues($file->fid)), 'No video_queue entry should be present after deleting all nodes');
    $this
      ->assertEqual(0, count($this
      ->getFileUsage($file->fid)), 'There should be no usage entries remaining after deleting all nodes');
    $this
      ->assertFalse(file_exists($file->uri), 'The file should be removed after deleting the video from all nodes');
  }

  /**
   * Tests validation logic in video_field_validate().
   */
  public function testVideoFieldValidate() {

    // Build test data
    $file = $this
      ->createFile('test.txt', 'text/plain');
    $node = new stdClass();
    $node->uid = $this->user->uid;
    $node->type = 'page';
    $node->title = 'Test node';
    $node->videofield['und'][0] = array(
      'fid' => $file->fid,
      'dimensions' => '100x60',
    );
    node_save($node);
  }
  private function createFile($name = 'file.mp4', $mime = 'video/mp4') {
    $dir = 'public://videos/original/';
    file_prepare_directory($dir, FILE_CREATE_DIRECTORY);
    $uri = $dir . $name;
    $filesize = 123;
    file_put_contents($uri, str_repeat('0', $filesize));
    $fid = db_insert('file_managed')
      ->fields(array(
      'filemime' => $mime,
      'uri' => $uri,
      'filename' => $name,
      'filesize' => $filesize,
      'status' => 0,
      'timestamp' => time(),
      'uid' => $this->user->uid,
    ))
      ->execute();
    return file_load(intval($fid));
  }
  private function getQueues($fid) {
    $queues = array();
    $result = db_query('SELECT q.* FROM {video_queue} q WHERE q.fid = :fid', array(
      ':fid' => $fid,
    ))
      ->fetchAll();
    foreach ($result as $q) {
      $q->data = unserialize($q->data);
      $queues[] = $q;
    }
    return $queues;
  }
  private function getConvertedFiles($originalfid) {
    return db_query('SELECT o.*, f.* FROM {video_output} o INNER JOIN {file_managed} f ON (f.fid = o.output_fid) WHERE o.original_fid = :fid', array(
      ':fid' => $originalfid,
    ))
      ->fetchAllAssoc('fid');
  }
  private function getThumbnailFiles($videofid) {
    return db_query('SELECT t.*, f.* FROM {video_thumbnails} t INNER JOIN {file_managed} f ON (f.fid = t.thumbnailfid) WHERE t.videofid = :fid', array(
      ':fid' => $videofid,
    ))
      ->fetchAllAssoc('fid');
  }
  private function getFileUsage($fid) {
    return db_query('SELECT u.* FROM {file_usage} u WHERE u.fid = :fid', array(
      ':fid' => $fid,
    ))
      ->fetchAll();
  }

  /**
   * Makes changes in the database such that a video looks transcoded.
   *
   * @todo use a fake transcoder class to transcode the file
   */
  private function transcodeVideo(stdClass &$node, $vid, $fid) {
    db_update('video_queue')
      ->fields(array(
      'status' => VIDEO_RENDERING_COMPLETE,
      'started' => time(),
      'completed' => time(),
    ))
      ->execute();

    // Converted file
    $of = $this
      ->createFile('video_' . $fid . '_transcoded.mp4');
    $of->status = FILE_STATUS_PERMANENT;
    file_save($of);
    db_insert('video_output')
      ->fields(array(
      'vid' => $vid,
      'original_fid' => $fid,
      'output_fid' => $of->fid,
    ))
      ->execute();

    // Thumbnails
    for ($i = 0; $i < variable_get('video_thumbnail_count', 5); $i++) {
      $tnf = $this
        ->createFile('thumbnail-' . $fid . '_' . sprintf('%04d', $i) . '.jpg', 'image/jpeg');
      $tnf->status = FILE_STATUS_PERMANENT;
      file_save($tnf);
      db_insert('video_thumbnails')
        ->fields(array(
        'videofid' => $fid,
        'thumbnailfid' => $tnf->fid,
      ))
        ->execute();
    }

    // Save the node to trigger usage generation
    node_save($node);
    $node = node_load($node->nid);
  }

}

Classes

Namesort descending Description
VideoFieldTestCase Tests for the the Video field type