You are here

varnish.test in Varnish 6

Same filename and directory in other branches
  1. 7 varnish.test

Tests the basic functionality of Varnish.

File

varnish.test
View source
<?php

/**
 * @file
 * Tests the basic functionality of Varnish.
 */

/**
 * Base class for Varnish Test Cases.
 */
class VarnishTestCase extends DrupalWebTestCase {
  static $varnish_config;
  function setUp() {

    // Save off varnish settings, we will need to set these later
    // on in order to perform tests.
    if (!isset($this->varnish_config)) {
      $this->varnish_config = array(
        'varnish_control_key' => variable_get('varnish_control_key', ''),
        'varnish_control_terminal' => variable_get('varnish_control_terminal', '127.0.0.1:6082'),
        'varnish_version' => variable_get('varnish_version', 2.1),
        'varnish_socket_timeout' => variable_get('varnish_socket_timeout', VARNISH_DEFAULT_TIMETOUT),
        // We always want this to be set to default.
        'varnish_cache_clear' => VARNISH_DEFAULT_CLEAR,
      );
    }
    parent::setUp('varnish', 'comment');
    $this
      ->setUpVariables();
    $this
      ->setUpPermissions();
  }

  /**
   * Set up variables so that drupal sends out appropriate headers
   * to Varnish.
   */
  function setUpVariables() {
    $variables = array(
      'cache' => 3,
      'cache_lifetime' => 900,
      'page_cache_max_age' => 1800,
    ) + $this->varnish_config;
    foreach ($variables as $key => $variable) {
      variable_set($key, $variable);
    }
    $this
      ->refreshVariables();
  }

  /**
   * Set up permissions for the anonymous user so that it's possible
   * to access all content that can be invalidated.
   */
  function setUpPermissions() {

    // Get the default permissions.
    $permissions = explode(', ', db_result(db_query("SELECT perm FROM {permission} WHERE rid = %d", 1)));

    // Assign access comments and access user profiles permission to anonymous users.
    $permissions[] = 'access comments';
    $permissions[] = 'access user profiles';
    db_query("DELETE FROM {permission} WHERE rid = %d", 1);
    db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", 1, implode(', ', $permissions));
  }

  /**
   * Create a comment.
   * @param array settings add whatever things you want on your comments.
   *  here. You must at least specify a nid.
   * @param stdClass comment_user provide a user if you want it to
   *  belong to certain user.
   */
  function createComment($settings, $comment_user = NULL) {
    global $user;
    $old_user = $user;
    if (!is_array($settings) && !is_numeric($settings['nid'])) {
      return FALSE;
    }
    if (isset($comment_user)) {
      $user = $comment_user;
    }
    $settings += array(
      'status' => COMMENT_PUBLISHED,
      'uid' => $user->uid,
      'pid' => 0,
      'subject' => $this
        ->randomName(),
      'format' => 1,
      'timestamp' => time(),
      'comment' => $this
        ->randomString(300),
      'cid' => 0,
    );
    $result = comment_save($settings);
    if ($result) {
      $settings['cid'] = $result;
      $result = $settings;
    }
    $user = $old_user;
    return $result;
  }

  /**
   * Delete a drupal comment.
   * @param $comment the comment object or array.
   */
  function deleteComment($comment) {

    // The comment is an array in comment_save, but it should be
    // an object when you delete it, so we do a conversion here in order
    // to avoid wtfs in the rest of the code.
    if (is_array($comment)) {
      $comment = (object) $comment;
    }

    // Functions for deleting comments resides in the admin.inc file.
    $status = module_load_include('admin.inc', 'comment');
    $this
      ->_commentDeleteHelper($comment);
  }

  /**
   * Does exactly the same thing that comment.module does.
   * @see comment_confirm_delete_submit()
   * @param object $comment the comment object.
   */
  function _commentDeleteHelper($comment) {

    // Delete comment and its replies.
    _comment_delete_thread($comment);
    _comment_update_node_statistics($comment->nid);

    // Clear the cache so an anonymous user sees that his comment was deleted.
    cache_clear_all();
  }

  /**
   * Run a varnish command and make sure it worked for us.
   * @param string $cmd the command to execute.
   */
  function assertVarnishCommand($cmds) {
    $statuses = _varnish_terminal_run($cmds);
    foreach ($statuses as $terminal => $commands) {
      foreach ($commands as $command => $status) {
        $this
          ->assertEqual($status['code'], '200', t('Command: %command
          was executed properly.', array(
          '%command' => $command,
        )));
      }
    }
  }

}

/**
 * Test Varnish Connection.
 */
class VarnishConnectionTestCase extends VarnishTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Varnish Connection',
      'description' => 'Test Communication between varnish admin terminal and Drupal.',
      'group' => 'Varnish',
    );
  }
  function testVarnishStatus() {
    $this
      ->assertVarnishCommand(array(
      'status',
    ));
  }
  function testVarnishStats() {
    if (variable_get('varnish_version', 2.1) < 3) {
      $this
        ->assertVarnishCommand(array(
        'stats',
      ));
    }
  }
  function testMultipleCommands() {
    $this
      ->assertVarnishCommand(array(
      'stats',
      'status',
    ));
  }

}
class VarnishCacheInvalidationCase extends VarnishTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Varnish Cache Expiration',
      'description' => 'Tests Cache Expiration.',
      'group' => 'Varnish',
    );
  }
  function setUp() {
    parent::setUp();

    // Expire all cached pages.
    varnish_purge_all_pages();
  }

  /**
   * Test that makes sure that the varnish cache doesn't get
   * invalidated when the varnish_cache_clear options is set to 0.
   */
  function testNoVarnishCacheExpiration() {

    // Tell Varnish Module to not expire anything.
    variable_set('varnish_cache_clear', 0);

    // Create a node.
    $node = $this
      ->drupalCreateNode();

    // Cache it in varnish by going to the node.
    $content = $this
      ->drupalGet('node/' . $node->nid);

    // The title should be what we expect, otherwise, something
    // is horribly wrong.
    $this
      ->assertText($node->title, t('The node title correct.'));
    $old_title = $node->title;

    // Change the node title
    $node->title = $this
      ->randomName(8);
    node_save($node);

    // Go to the node again. The title should not have changed.
    $this
      ->drupalGet('node/' . $node->nid);
    $this
      ->assertText($old_title, t('The node title did not change when
     varnish is set to not invalidate the cache.'));
  }

  /**
   * Test that makes sure the Node Cache Expiration works as intended.
   */
  function testNodeCacheExpiration() {
    varnish_purge_all_pages();

    // Tell Varnish Module to follow the same rules as the
    // drupal cache expiration logic does.
    variable_set('varnish_cache_clear', VARNISH_DEFAULT_CLEAR);

    // Cache the standard node listing.
    $this
      ->drupalGet('node');

    // Create a node.
    $node = $this
      ->drupalCreateNode(array(
      'promote' => 1,
    ));

    // Make sure the node shows up in the standard node listing.
    $this
      ->drupalGet('node');
    $this
      ->assertText($node->title, t('The node title was found.'));

    // Cache the node in varnish by going to the node.
    $content = $this
      ->drupalGet('node/' . $node->nid);

    // The title should be what we expect, otherwise, something
    // is horribly wrong.
    $this
      ->assertText($node->title, t('The node title was found on the
      node page.'));

    // Change the node title
    $node->title = $this
      ->randomName(8);
    node_save($node);

    // Go to the node again. The title should have been changed.
    $this
      ->drupalGet('node/' . $node->nid);
    $this
      ->assertText($node->title, t('The node title did change when
      varnish is set to not invalidate the cache.'));

    // Go to the node listing. The title should have been updated.
    $this
      ->drupalGet('node');
    $this
      ->assertText($node->title, t('The changed node title was
      found on the node listing.'));

    // Delete the node. It should disappear from the node listing.
    node_delete($node->nid);
    $this
      ->drupalGet('node');
    $this
      ->assertNoText($node->title, t('The node title of the deleted node
      did not show up in the node listing.'));
  }

  /**
   * Test that makes sure that the comment expiration works as expected.
   */
  function testCommentCacheExpiration() {

    // Create a node.
    $node = $this
      ->drupalCreateNode(array(
      'promote' => 1,
      'type' => 'article',
    ));

    // Create a user.
    $user = $this
      ->drupalCreateUser();

    // Cache the standard node listing.
    $this
      ->drupalGet('node/' . $node->nid);

    // Create a comment on the node.
    $comment = $this
      ->createComment(array(
      'nid' => $node->nid,
    ), $user);
    $this
      ->assertNotEqual($comment, FALSE, t('Comment was created without problems.'));

    // Check the node again. It should be updated with the new content.
    $data = $this
      ->drupalGet('node/' . $node->nid);
    $this
      ->assertText($comment['subject'], t('The comment subject %subject was
      found', array(
      '%subject' => $comment['subject'],
    )));

    // Update the comment and see that it gets updated on the node page.
    $comment['subject'] = $this
      ->randomName();
    comment_save($comment);
    $this
      ->drupalGet('node/' . $node->nid);
    $this
      ->assertText($comment['subject'], t('The changed comment subject
      %subject was found', array(
      '%subject' => $comment['subject'],
    )));

    // Delete the comment and see that it gets removed from the node page.
    $this
      ->deleteComment($comment);
    $this
      ->drupalGet('node/' . $node->nid);
    $this
      ->assertNoText($comment['subject'], t('The comment subject
      %subject of the deleted node was not found.', array(
      '%subject' => $comment['subject'],
    )));
  }

  /**
   * Test that makes sure that the user cache expiration works as intended.
   */
  function testUserCacheExpiration() {

    // Create a user.
    $user = $this
      ->drupalCreateUser();

    // Cache it in varnish.
    $this
      ->drupalGet('user/' . $user->uid);

    // Make sure the user name is present.
    $this
      ->assertText($user->name, t('The user name %name
      is present on the profile page.', array(
      '%name' => $user->name,
    )));

    // Change the user name.
    $user->name = $this
      ->randomName();
    user_save($user, (array) $user);

    // Go to the user page. It cache should have been invalidated.
    $this
      ->drupalGet('user/' . $user->uid);
    $this
      ->assertText($user->name, t('The changed user name %name is
      present on the profile page.', array(
      '%name' => $user->name,
    )));
  }

}
class VarnishAdminTestCase extends VarnishTestCase {
  var $admin_user;
  public static function getInfo() {
    return array(
      'name' => 'Varnish Administration',
      'description' => 'Tests Varnish Administration.',
      'group' => 'Varnish',
    );
  }
  function setUp() {
    parent::setUp();

    // Create a user that can administrate varnish.
    $permissions = array(
      'administer varnish',
      'access administration pages',
      'administer site configuration',
      'access content',
    );
    $this->admin_user = $this
      ->drupalCreateUser($permissions);
  }

  /**
   * Test the clear cache button in the admin UI.
   */
  function testCacheClearButton() {

    // Expire all cached pages.
    varnish_purge_all_pages();

    // Tell Varnish Module to not expire anything.
    variable_set('varnish_cache_clear', 0);

    // Cache the node listing page.
    $this
      ->drupalGet('node');

    // Create a node.
    $node = $this
      ->drupalCreateNode(array(
      'promote' => 1,
    ));

    // Go to the page again. The node should not exist.
    $this
      ->drupalGet('node');
    $this
      ->assertNoText($node->title, t('The node is not present on the front page.'));

    // Log in as administrator.
    $this
      ->drupalLogin($this->admin_user);

    // Go to the performance form.
    $this
      ->drupalGet('admin/settings/performance');

    // Click the clear cache button.
    $this
      ->drupalPost('admin/settings/performance', array(), t('Clear cached data'));
    $this
      ->drupalLogout();

    // Go to the node listing. The node should be present.
    $this
      ->drupalGet('node');
    $this
      ->assertText($node->title, t('The node is present after using the clear cache button.'));
  }
  function testVarnishSettingsPage() {
    $this
      ->drupalLogin($this->admin_user);
    $this
      ->drupalGet('admin/settings/varnish');
    $values = $this
      ->_getVarnishSettingsValues();

    // Try to set the timeout value to something else than a numeric value.
    // This should result in an error.
    $values['varnish_socket_timeout'] = 'asdf';
    $this
      ->drupalPost('admin/settings/varnish', $values, t('Save configuration'));
    $this
      ->assertText(t('Varnish connection timeout must be a positive number.'), t('Error message was given trying to set timeout to a string.'));
  }
  function _getVarnishSettingsValues() {
    return array(
      'varnish_control_terminal' => variable_get('varnish_control_terminal', '127.0.0.1:6082'),
      'varnish_flush_cron' => variable_get('varnish_flush_cron', 0),
      'varnish_version' => variable_get('varnish_version', 0),
      'varnish_control_key' => variable_get('varnish_control_key', 0),
      'varnish_socket_timeout' => variable_get('varnish_socket_timeout', 100),
      'varnish_cache_clear' => variable_get('varnish_cache_clear', 0),
    );
  }

}

Classes

Namesort descending Description
VarnishAdminTestCase
VarnishCacheInvalidationCase
VarnishConnectionTestCase Test Varnish Connection.
VarnishTestCase Base class for Varnish Test Cases.