You are here

RestfulRateLimitTestCase.test in RESTful 7

Same filename and directory in other branches
  1. 7.2 tests/RestfulRateLimitTestCase.test

Contains RestfulRateLimitTestCase.

File

tests/RestfulRateLimitTestCase.test
View source
<?php

/**
 * @file
 * Contains RestfulRateLimitTestCase.
 */
class RestfulRateLimitTestCase extends DrupalWebTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Rate limits',
      'description' => 'Test the rate limit feature.',
      'group' => 'RESTful',
    );
  }
  public function setUp() {
    parent::setUp('restful_example');
    $settings = array(
      'type' => 'article',
    );
    $titles = array(
      'abc',
      'xyz',
      'efg',
    );
    foreach ($titles as $title) {
      $settings['title'] = $title;
      $node = $this
        ->drupalCreateNode($settings);
      $nodes[$title] = $node->nid;
    }
  }

  /**
   * Tests global rate limits.
   */
  public function testGlobalLimits() {

    // Test the global limit.
    variable_set('restful_global_rate_limit', 1);

    // P3D for 3 days period. See
    // http://php.net/manual/en/class.dateinterval.php for more information
    // about the interval format.
    variable_set('restful_global_rate_period', 'P3D');
    $account = $this
      ->drupalCreateUser();
    $this
      ->roleExecute($account, 1, array(
      'articles',
      1,
      0,
    ));

    // Test invalid 'restful_global_rate_period' format.
    try {
      variable_set('restful_global_rate_period', 'fail');
      $this
        ->roleExecute($account, 1, array(
        'articles',
        1,
        0,
      ));
      $this
        ->fail('Invalid \\DateInterval format in restful_global_rate_period did not raise an error');
    } catch (Exception $e) {
      $this
        ->pass('Invalid \\DateInterval format in restful_global_rate_period raises an error');
    }
  }

  /**
   * Tests the rate limits and its expiration feature.
   */
  public function testLimits() {
    variable_del('restful_global_rate_limit');
    variable_del('restful_global_rate_period');

    // This handler has a limit of 2 requests for the anonymous user.
    $account = drupal_anonymous_user();
    $this
      ->roleExecute($account, 2, array(
      'articles',
      1,
      4,
    ));

    // This handler has a limit of 3 requests for the authenticated user.
    $account = $this
      ->drupalCreateUser();
    $this
      ->roleExecute($account, 3, array(
      'articles',
      1,
      4,
    ));

    // Now that the limit has been reached for $account. Fake expiration and see
    // that the limit has been renewed.
    $query = new \EntityFieldQuery();
    $results = $query
      ->entityCondition('entity_type', 'rate_limit')
      ->entityCondition('bundle', 'request')
      ->propertyCondition('identifier', 'articles::request::' . $account->uid)
      ->execute();
    $rl = entity_load_single('rate_limit', key($results['rate_limit']));
    $rl->timestamp = REQUEST_TIME - 2;
    $rl->expiration = REQUEST_TIME - 1;
    $rl
      ->save();
    $this
      ->roleExecute($account, 3, array(
      'articles',
      1,
      4,
    ));
  }

  /**
   * Tests the total amount of allowed calls and the following fail.
   *
   * @param $account
   *   The user account object.
   * @param $limit
   *   The number of calls allowed for a user with the same roles as $account.
   * @param $resource_options
   *   Array of options as received in restful_get_restful_handler.
   */
  protected function roleExecute($account, $limit, $resource_options) {
    $handler = restful_get_restful_handler($resource_options[0], $resource_options[1], $resource_options[2]);
    $handler
      ->setAccount($account);

    // Test rate limits.
    for ($count = 0; $count < $limit; $count++) {
      try {
        $handler
          ->get('');
        $this
          ->pass('The rate limit authorized the request.');
      } catch (\RestfulFloodException $e) {
        $this
          ->fail('The rate limit did not authorize the request.');
      }
    }
    try {
      $handler
        ->get('');
      $this
        ->fail('The rate limit authorized the request.');
    } catch (\RestfulFloodException $e) {
      $this
        ->pass('The rate limit did not authorize the request.');
      $headers = $e
        ->getHeaders();
      $this
        ->assertTrue(in_array('Retry-After', array_keys($headers)), 'Retry-After header found after rate limit exception.');
      $this
        ->assertTrue(new \DateTime($headers['Retry-After']) > new \DateTime(), 'Retry-After is set to a time in the future.');
    }
  }

}

Classes

Namesort descending Description
RestfulRateLimitTestCase @file Contains RestfulRateLimitTestCase.