You are here

password_policy.test in Password Policy 7.2

Unit tests for Password policy module.

File

password_policy.test
View source
<?php

/**
 * @file
 * Unit tests for Password policy module.
 */

/**
 * Base test case class for Password Policy.
 */
class PasswordPolicyBaseTestCase extends DrupalWebTestCase {
  protected $testPolicy;

  /**
   * Implements DrupalWebTestCase::setUp().
   */
  public function setUp() {
    parent::setUp('password_policy', 'password_policy_test');
    $this->account = $this
      ->drupalCreateUser();
    $this->testPolicy = $this
      ->createPolicy();
  }

  /**
   * Updates user password.
   *
   * @param object|null $account
   *   User object or NULL.
   *
   * @return object
   *   A fully loaded user object with pass_raw property.
   */
  protected function updateUserPassword($account = NULL) {
    if ($account === NULL) {
      $account = $this->account;
    }
    $edit = array(
      'pass' => user_password(),
    );
    user_save($account, $edit);
    $account = user_load($account->uid);

    // Add the raw password so that we can log in as this user.
    $account->pass_raw = $edit['pass'];
    return $account;
  }

  /**
   * Creates policy.
   *
   * @param array $config
   *   Configuration.
   *
   * @return PasswordPolicy
   *   Policy.
   */
  protected function createPolicy(array $config = array()) {
    $policy = new stdClass();
    $policy->disabled = FALSE;
    $policy->api_version = 1;
    $policy->name = 'Test policy';
    $policy->config = serialize($config);
    return new PasswordPolicy($policy);
  }

  /**
   * Checks password versus policy.
   *
   * @param PasswordPolicy $policy
   *   Policy.
   * @param string $password
   *   Password.
   * @param object|null $account
   *   User object or NULL.
   *
   * @return bool
   *   TRUE if the password passes all policy checks, FALSE otherwise.
   */
  protected function checkPolicy(PasswordPolicy $policy, $password, $account = NULL) {
    if ($account === NULL) {
      $account = $this->account;
    }
    $errors = $policy
      ->check($password, $account);
    return count($errors) == 0;
  }

  /**
   * Determines whether account matches policy.
   *
   * That is, determines whether account is covered by a given policy.
   *
   * @param PasswordPolicy $policy
   *   Policy.
   * @param object $account
   *   User object.
   *
   * @return bool
   *   TRUE if the account matches the policy, FALSE otherwise.
   */
  protected function matchPolicy(PasswordPolicy $policy, $account = NULL) {
    if ($account === NULL) {
      $account = $this->account;
    }
    return $policy
      ->match($account);
  }

}

/**
 * Basic test case for creating and executing Password Policies.
 */
class PasswordPolicyTestCase extends PasswordPolicyBaseTestCase {

  /**
   * Implements DrupalWebTestCase::getInfo().
   */
  public static function getInfo() {
    return array(
      'name' => 'Password policy management',
      'description' => 'Test creating and loading password policies.',
      'group' => 'Password Policy',
    );
  }

  /**
   * Tests the creation of an empty policy.
   */
  public function testCreatePolicy() {
    $this
      ->assertNotNull($this->testPolicy, 'Test password policy created successfully.');
  }

  /**
   * Tests the loading of CTools-based policies.
   */
  public function testLoadPolicy() {

    // Check for a policy contained in the Password Policy Test module.
    $policies = PasswordPolicy::enabledPolicies();
    $this
      ->assertTrue(array_key_exists('Test policy', $policies), 'Test policy exists when loaded via CTools.');
  }

}

/**
 * Test case to verify accuracy of each available policy constraint.
 */
class PasswordPolicyConstraintsTestCase extends PasswordPolicyBaseTestCase {

  /**
   * Implements DrupalWebTestCase::getInfo().
   */
  public static function getInfo() {
    return array(
      'name' => 'Password constraints',
      'description' => 'Test password constraints.',
      'group' => 'Password Policy',
    );
  }

  /**
   * Tests case sensitivity constraint.
   */
  public function testAlphaCaseConstraint() {
    $config = array(
      'alpha_case' => array(
        'alpha_case' => TRUE,
      ),
    );
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertFalse($this
      ->checkPolicy($policy, 'A'), 'Case sensivity constraint fails with only upper case letters.', 'Constraint');
    $this
      ->assertFalse($this
      ->checkPolicy($policy, 'a'), 'Case sensivity fails with only lower case letters.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'Aa'), 'Case sensivity constraint passes with both lower and upper case letters.', 'Constraint');
  }

  /**
   * Tests letter count constraint.
   */
  public function testAlphaCountConstraint() {
    $config = array(
      'alpha_count' => array(
        'alpha_count' => 1,
      ),
    );
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertFalse($this
      ->checkPolicy($policy, ''), 'Letter count constraint fails with less than required letters.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'a'), 'Letter count constraint passes with minimum required letters.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'a1'), 'Letter count constraint passes with more than required letters.', 'Constraint');
  }

  /**
   * Tests blacklist constraint.
   */
  public function testBlacklistConstraint() {

    // Whitespace in blacklist helps test trimming of blacklisted passwords.
    $config = array(
      'blacklist' => array(
        'blacklist' => "123\n abc\t\ndef",
        'blacklist_match_substrings' => FALSE,
      ),
    );
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertFalse($this
      ->checkPolicy($policy, 'ABC'), 'Blacklist constraint fails with password in blacklist.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'foo'), 'Blacklist constraint passes with password not in blacklist.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'abc123'), 'Blacklist constraint passes with password containing but not equaling blacklisted passwords.', 'Constraint');

    // Test policy that disallows passwords containing blacklisted passwords.
    $config['blacklist']['blacklist_match_substrings'] = TRUE;
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertFalse($this
      ->checkPolicy($policy, 'ABC'), 'Blacklist constraint fails with password in blacklist.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'foo'), 'Blacklist constraint passes with password not in blacklist.', 'Constraint');
    $this
      ->assertFalse($this
      ->checkPolicy($policy, 'abc123'), 'Blacklist constraint fails with password containing but not equaling blacklisted passwords.', 'Constraint');
  }

  /**
   * Tests character count constraint.
   */
  public function testCharCountConstraint() {
    $config = array(
      'char_count' => array(
        'char_count' => 1,
      ),
    );
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertFalse($this
      ->checkPolicy($policy, ''), 'Character count constraint fails with less than required characters.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'a'), 'Character count constraint passes with minimum required characters.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'ab'), 'Character count constraint passes with more than required characters.', 'Constraint');
  }

  /**
   * Tests consecutive count constraint.
   */
  public function testConsecutiveConstraint() {
    $config = array(
      'consecutive' => array(
        'consecutive_char_count' => 2,
      ),
    );
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'a'), 'Consecutive character count constraint passes with fewer than maximum consecutive characters.', 'Constraint');
    $this
      ->assertFalse($this
      ->checkPolicy($policy, 'aa'), 'Consecutive character count constraint fails with exact maximum consecutive characters.', 'Constraint');
    $this
      ->assertFalse($this
      ->checkPolicy($policy, 'aaa'), 'Consecutive character count constraint fails with more than maximum consecutive characters.', 'Constraint');
  }

  /**
   * Tests delay constraint.
   */
  public function testDelayConstraint() {
    $policy = $this
      ->createPolicy(array(
      'delay' => array(
        'delay' => '24 hours',
      ),
    ));
    $this
      ->assertFalse($this
      ->checkPolicy($policy, 'password', $this->account), 'Delay constraint fails with new password before delay window expires.', 'Constraint');
    $policy = $this
      ->createPolicy(array(
      'delay' => array(
        'delay' => '1 sec',
      ),
    ));
    sleep(2);
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'password', $this->account), 'Delay constraint passes with new password after delay window expires.', 'Constraint');
    $policy = $this
      ->createPolicy(array(
      'delay' => array(
        'delay' => '24 hours',
        'threshold' => 2,
      ),
    ));
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'password', $this->account), 'Delay constraint passes with new password before delay window expires but threshold is not reached.', 'Constraint');
    $this->account = $this
      ->updateUserPassword($this->account);
    $this
      ->assertFalse($this
      ->checkPolicy($policy, 'password', $this->account), 'Delay constraint fails with new password before delay window expires and threshold is reached.', 'Constraint');
  }

  /**
   * Tests integer count constraint.
   */
  public function testIntCountConstraint() {
    $config = array(
      'int_count' => array(
        'int_count' => 1,
      ),
    );
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertFalse($this
      ->checkPolicy($policy, ''), 'Integer count constraint fails with less than required integers.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, '1'), 'Integer count constraint passes with minimum required integers.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, '12'), 'Integer count constraint passes with more than required integers.', 'Constraint');
  }

  /**
   * Tests special character count constraint.
   */
  public function testSpecialCharCountConstraint() {
    $config = array(
      'special_count' => array(
        'special_count' => 1,
      ),
    );
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertFalse($this
      ->checkPolicy($policy, 'a'), 'Special character count constraint fails with less than required special characters.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, 'a$'), 'Special character count constraint passes with minimum required special characters.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, '&a$'), 'Special character count constraint passes with more than required special characters.', 'Constraint');
  }

  /**
   * Tests username constraint.
   */
  public function testUsernameConstraint() {
    $config = array(
      'username' => array(
        'username' => TRUE,
      ),
    );
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertFalse($this
      ->checkPolicy($policy, $this->account->name), 'Username constraint fails with username present.', 'Constraint');
    $this
      ->assertTrue($this
      ->checkPolicy($policy, ''), 'Username constraint passes with username absent.', 'Constraint');
  }

}

/**
 * Test case to verify accuracy of each available policy condition.
 */
class PasswordPolicyConditionsTestCase extends PasswordPolicyBaseTestCase {

  /**
   * Implements DrupalWebTestCase::getInfo().
   */
  public static function getInfo() {
    return array(
      'name' => 'Password policy conditions',
      'description' => 'Test password policy conditions.',
      'group' => 'Password Policy',
    );
  }

  /**
   * Tests role condition.
   */
  public function testRoleCondition() {
    $rid = $this
      ->drupalCreateRole(array());
    $config = array(
      'role' => array(
        'roles' => array(
          $rid => 1,
        ),
      ),
    );
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertFalse($this
      ->matchPolicy($policy), 'Role condition fails with unprivileged account.', 'Condition');

    // Add role to user in order to match the condition.
    $this->account->roles[$rid] = 'test role';
    $this
      ->assertTrue($this
      ->matchPolicy($policy), 'Role condition passes with privileged account.', 'Condition');
  }

  /**
   * Tests authmap condition.
   */
  public function testAuthmapCondition() {
    $config = array(
      'authmap' => array(
        'authmodules' => array(
          'auth_module_one' => 'auth_module_one',
        ),
      ),
    );
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertTrue($this
      ->matchPolicy($policy, drupal_anonymous_user()), 'Authmap condition passes for anonymous user.', 'Condition');
    $this
      ->assertTrue($this
      ->matchPolicy($policy), 'Authmap condition passes with account not mapped to external authentication module.', 'Condition');

    // Add authmap to user so that the condition does not match.
    $authmaps = array(
      'authname_auth_module_one' => $this->account->name,
    );
    user_set_authmaps($this->account, $authmaps);
    $this
      ->assertFalse($this
      ->matchPolicy($policy), 'Authmap condition fails with account mapped to excluded external authentication module.', 'Condition');

    // Exclude a different authentication module to match the condition.
    $config = array(
      'authmap' => array(
        'authmodules' => array(
          'auth_module_two' => 'auth_module_two',
        ),
      ),
    );
    $policy = $this
      ->createPolicy($config);
    $this
      ->assertTrue($this
      ->matchPolicy($policy), 'Authmap condition passes with account mapped to included external authentication module.', 'Condition');
  }

  /**
   * Tests using multiple conditions.
   *
   * The policy should be applied if all conditions pass. That is, a Boolean
   * AND is performed on the conditions.
   */
  public function testMultipleConditions() {

    // Create policy with two conditions.
    $rid = $this
      ->drupalCreateRole(array());
    $config = array(
      'role' => array(
        'roles' => array(
          $rid => 1,
        ),
      ),
      'authmap' => array(
        'authmodules' => array(
          'auth_module_one' => 'auth_module_one',
        ),
      ),
    );
    $policy = $this
      ->createPolicy($config);

    // Test condition #1 fail and condition #2 pass.
    $this
      ->assertFalse($this
      ->matchPolicy($policy), 'Role condition fails and authmap condition passes: Policy does not match.', 'Condition');

    // Test condition #1 pass and condition #2 pass.
    $this->account->roles[$rid] = 'test role';
    $this
      ->assertTrue($this
      ->matchPolicy($policy), 'Role condition passes and authmap condition passes: Policy matches.', 'Condition');

    // Test condition #1 pass and condition #2 fail.
    $authmaps = array(
      'authname_auth_module_one' => $this->account->name,
    );
    user_set_authmaps($this->account, $authmaps);
    $this
      ->assertFalse($this
      ->matchPolicy($policy), 'Role condition passes and authmap condition fails: Policy does not match.', 'Condition');

    // Test condition #1 fail and condition #2 fail.
    unset($this->account->roles[$rid]);
    $this
      ->assertFalse($this
      ->matchPolicy($policy), 'Role condition fails and authmap condition fails: Policy does not match.', 'Condition');
  }

}

/**
 * Tests of restriction on password length.
 */
class PasswordPolicyPasswordLengthRestrictionTestCase extends PasswordPolicyBaseTestCase {
  protected $admin;

  /**
   * Implements DrupalWebTestCase::getInfo().
   */
  public static function getInfo() {
    return array(
      'name' => 'Password length restriction',
      'description' => 'Test that overlong passwords are disallowed.',
      'group' => 'Password Policy',
    );
  }

  /**
   * Set up the test.
   */
  public function setUp() {
    parent::setUp('password_policy');
    $this
      ->createAdmin();
  }

  /**
   * Creates a usable admin (UID=1) user.
   *
   * SimpleTest creates an admin user, but it cannot log in since it has no
   * password set. So, we give it a password. We also give it a valid email
   * address so its user edit form can be submitted.
   */
  protected function createAdmin() {
    global $user;
    $pass = user_password();
    $edit = array(
      'pass' => $pass,
      'mail' => 'foo@example.com',
    );
    user_save($user, $edit);
    $user->pass_raw = $pass;
    $this->admin = $user;
  }

  /**
   * Sets a password policy that applies to the authenticated user role.
   *
   * This is just a minimal policy to apply to the admin (UID=1) user, which is
   * being used for this test.
   */
  public function testOverlongPasswordSubmission() {
    $config = array(
      'alpha_count' => array(
        'alpha_count' => 1,
      ),
      'role' => array(
        'roles' => array(
          DRUPAL_AUTHENTICATED_RID => 1,
        ),
      ),
    );
    $this
      ->createPolicy($config);
    $this
      ->drupalLogin($this->admin);
    $this
      ->submitOverlongPassword();
    $this
      ->submitNotOverlongPassword();
  }

  /**
   * Submits a password that is overlong.
   */
  protected function submitOverlongPassword() {
    $pass = str_repeat('a', 513);
    $edit = array(
      'current_pass' => $this->admin->pass_raw,
      'pass[pass1]' => $pass,
      'pass[pass2]' => $pass,
    );
    $this
      ->drupalPost('user/' . $this->admin->uid . '/edit', $edit, t('Save'));
    $this
      ->assertText(t('Password exceeds maximum length.'), 'Overlong password causes form error.');
    $this
      ->assertNoText(t('The changes have been saved.'), 'Overlong password is not saved.');
  }

  /**
   * Submits a password that is not overlong.
   */
  protected function submitNotOverlongPassword() {
    $pass = str_repeat('a', 512);
    $edit = array(
      'current_pass' => $this->admin->pass_raw,
      'pass[pass1]' => $pass,
      'pass[pass2]' => $pass,
    );
    $this
      ->drupalPost('user/' . $this->admin->uid . '/edit', $edit, t('Save'));
    $this
      ->assertNoText(t('Password exceeds maximum length.'), 'Not-overlong password does not cause form error.');
    $this
      ->assertText(t('The changes have been saved.'), 'Not-overlong password is saved.');
  }

}

/**
 * Test case to verify accuracy of each available policy condition.
 */
class PasswordPolicyUITestCase extends DrupalWebTestCase {

  /**
   * Implements DrupalWebTestCase::getInfo().
   */
  public static function getInfo() {
    return array(
      'name' => 'Password Policy UI',
      'description' => 'Test the Password Policy user interface.',
      'group' => 'Password Policy',
    );
  }

  /**
   * Sets up the test.
   */
  public function setUp() {
    parent::setUp('password_policy', 'password_policy_test');

    // Include ctools export so password policies can be created
    // progammatically.
    ctools_include('export');
  }

  /**
   * Creates a strong policy.
   */
  protected function createStrongPolicy() {

    // Set up strong policy.
    $password_policy = new stdClass();
    $password_policy->disabled = FALSE;
    $password_policy->api_version = 1;
    $password_policy->name = 'strong';
    $password_policy->export_type = NULL;
    $config = array(
      'alpha_count' => array(
        'alpha_count' => '1',
      ),
      'char_count' => array(
        'char_count' => '8',
      ),
      'consecutive' => array(
        'consecutive_char_count' => '',
      ),
      'int_count' => array(
        'int_count' => '1',
      ),
      'past_passwords' => array(
        'past_passwords' => '2',
      ),
      'special_count' => array(
        'special_count' => '0',
        'special_count_chars' => '`~!@#$%^&*()_+=-|}{"?:><,./;\'\\[]',
      ),
      'username' => array(
        'username' => TRUE,
      ),
      'role' => array(
        'roles' => array(
          2 => 0,
          3 => 0,
        ),
      ),
      'expire' => array(
        'expire_limit' => '0',
        'expire_warning_email_sent' => '-14 days',
        'expire_warning_email_message' => '',
        'expire_warning_email_subject' => '[user:name] you password on [site:name] shall expire in [password_expiration_date:interval]',
      ),
    );
    $password_policy->config = serialize($config);
    ctools_export_crud_save('password_policy', $password_policy);
  }

  /**
   * Creates a policy configured for password expiration.
   */
  protected function createExpirePolicy() {

    // Set up expire policy.
    $password_policy = new stdClass();
    $password_policy->disabled = FALSE;
    $password_policy->api_version = 1;
    $password_policy->name = 'expire';
    $password_policy->export_type = NULL;
    $config = array(
      'alpha_count' => array(
        'alpha_count' => '0',
      ),
      'char_count' => array(
        'char_count' => '0',
      ),
      'consecutive' => array(
        'consecutive_char_count' => '',
      ),
      'int_count' => array(
        'int_count' => '0',
      ),
      'past_passwords' => array(
        'past_passwords' => '0',
      ),
      'special_count' => array(
        'special_count' => '0',
        'special_count_chars' => '`~!@#$%^&*()_+=-|}{"?:><,./;\'\\[]',
      ),
      'username' => array(
        'username' => TRUE,
      ),
      'role' => array(
        'roles' => array(
          2 => 0,
          3 => 0,
        ),
      ),
      'expire' => array(
        'expire_enabled' => TRUE,
        'expire_limit' => '1 second',
        'expire_warning_email_sent' => '',
        'expire_warning_email_message' => '',
        'expire_warning_email_subject' => '[user:name] you password on [site:name] shall expire in [password_expiration_date:interval]',
      ),
    );
    $password_policy->config = serialize($config);
    ctools_export_crud_save('password_policy', $password_policy);
  }

  /**
   * Tests password policy enforcement on registration.
   */
  public function testRegistration() {

    // Create strong policy.
    $this
      ->createStrongPolicy();

    // Don't require e-mail verification.
    variable_set('user_email_verification', FALSE);

    // Allow registration by site visitors without administrator approval.
    variable_set('user_register', USER_REGISTER_VISITORS);
    $edit = array();
    $edit['name'] = $this
      ->randomName();
    $edit['mail'] = $edit['name'] . '@example.com';

    // Try a weak password.
    $edit['pass[pass1]'] = 'pass';
    $edit['pass[pass2]'] = 'pass';
    $this
      ->drupalPost('user/register', $edit, t('Create new account'));
    $this
      ->assertText('Password must have at least 1 digit(s).');
    $this
      ->assertText('Password must have at least 8 character(s).');
  }

  /**
   * Tests setting passwords.
   */
  public function testPasswordSet() {

    // Use password_policy_test module form_alter to prevent extraneous policy
    // text on user edit page. @todo figure out another way to do this.
    variable_set('password_policy_test_no_description', TRUE);

    // Set up strong policy.
    $this
      ->createStrongPolicy();
    $user = $this
      ->drupalCreateUser();
    $this
      ->drupalLogin($user);

    // Hold onto first password.
    $password0 = $user->pass_raw;

    // Try weak password.
    $edit = array();
    $edit['current_pass'] = $password0;
    $edit['pass[pass1]'] = 'pass';
    $edit['pass[pass2]'] = 'pass';
    $this
      ->drupalPost("user/{$user->uid}/edit", $edit, t('Save'));
    $this
      ->assertText('Password must have at least 1 digit(s).');
    $this
      ->assertText('Password must have at least 8 character(s).');

    // Try username.
    $edit = array();
    $edit['current_pass'] = $password0;
    $edit['pass[pass1]'] = $user->name;
    $edit['pass[pass2]'] = $user->name;
    $this
      ->drupalPost("user/{$user->uid}/edit", $edit, t('Save'));
    $this
      ->assertText('Password must not contain their username');

    // Change password twice.
    $password1 = $this
      ->randomName() . '9';
    $edit = array();
    $edit['current_pass'] = $password0;
    $edit['pass[pass1]'] = $password1;
    $edit['pass[pass2]'] = $password1;
    $this
      ->drupalPost("user/{$user->uid}/edit", $edit, t('Save'));
    $password2 = $this
      ->randomName() . '9';
    $edit = array();
    $edit['current_pass'] = $password1;
    $edit['pass[pass1]'] = $password2;
    $edit['pass[pass2]'] = $password2;
    $this
      ->drupalPost("user/{$user->uid}/edit", $edit, t('Save'));
    $this
      ->assertText('The changes have been saved.');

    // Try to save old $password1.
    $edit = array();
    $edit['current_pass'] = $password2;
    $edit['pass[pass1]'] = $password1;
    $edit['pass[pass2]'] = $password1;
    $this
      ->drupalPost("user/{$user->uid}/edit", $edit, t('Save'));
    $this
      ->assertNoText('The changes have been saved.');
    $this
      ->assertText('Password cannot match 2 past passwords.');

    // Save a new random password.
    $password3 = $this
      ->randomName() . '9';
    $edit = array();
    $edit['current_pass'] = $password2;
    $edit['pass[pass1]'] = $password3;
    $edit['pass[pass2]'] = $password3;
    $this
      ->drupalPost("user/{$user->uid}/edit", $edit, t('Save'));
    $this
      ->assertText('The changes have been saved.');

    // Try and save $password1.
    $edit = array();
    $edit['current_pass'] = $password3;
    $edit['pass[pass1]'] = $password1;
    $edit['pass[pass2]'] = $password1;
    $this
      ->drupalPost("user/{$user->uid}/edit", $edit, t('Save'));
    $this
      ->assertText('The changes have been saved.');
  }

  /**
   * Test expire functionality.
   */
  public function testExpire() {

    // Use password_policy_test module form_alter to prevent extraneous policy
    // text on user edit page. @todo figure out another way to do this.
    variable_set('password_policy_test_no_description', TRUE);
    $user = $this
      ->drupalCreateUser();
    $this
      ->drupalLogin($user);

    // Set up expire policy.
    $this
      ->createExpirePolicy();

    // Sleep to force simpletest to exceed 1 second expire.
    sleep(2);
    $this
      ->drupalGet('filter/tips');
    $this
      ->assertText('Your password has expired. Please change it now.');
    $this
      ->assertFieldByName('pass[pass1]', '', 'Password entry field appears.');

    // Change password.
    $password1 = $this
      ->randomName() . '9';
    $edit = array();
    $edit['current_pass'] = $user->pass_raw;
    $edit['pass[pass1]'] = $password1;
    $edit['pass[pass2]'] = $password1;
    $this
      ->drupalPost("user/{$user->uid}/edit", $edit, t('Save'));
    $this
      ->assertText('The changes have been saved.');
    $user->pass_raw = $password1;
    $this
      ->drupalLogout();

    // Artificially lengthen expiration to give administrator time to disable.
    $info = ctools_export_crud_load('password_policy', 'expire');
    $config = unserialize($info->config);
    $config['expire']['expire_limit'] = '30 minutes';
    $info->config = serialize($config);
    ctools_export_crud_save('password_policy', $info);

    // Disable expire.
    $admin = $this
      ->drupalCreateUser(array(
      'administer password policy',
    ));
    $this
      ->drupalLogin($admin);
    $path = 'admin/config/people/password_policy/list/expire/edit';
    $edit = array(
      'expire_enabled' => FALSE,
    );
    $this
      ->drupalPost($path, $edit, t('Save'));
    $this
      ->drupalLogout();

    // Reset expiration to one second.
    ctools_export_load_object_reset('password_policy');
    $info = ctools_export_crud_load('password_policy', 'expire');
    $config = unserialize($info->config);
    $config['expire']['expire_limit'] = '1 second';
    $info->config = serialize($config);
    ctools_export_crud_save('password_policy', $info);

    // Confirm expire disabled.
    sleep(2);
    $this
      ->drupalLogin($user);
    $this
      ->drupalGet('filter/tips');
    $this
      ->assertNoText('Your password has expired. Please change it now.');
  }

}

Classes

Namesort descending Description
PasswordPolicyBaseTestCase Base test case class for Password Policy.
PasswordPolicyConditionsTestCase Test case to verify accuracy of each available policy condition.
PasswordPolicyConstraintsTestCase Test case to verify accuracy of each available policy constraint.
PasswordPolicyPasswordLengthRestrictionTestCase Tests of restriction on password length.
PasswordPolicyTestCase Basic test case for creating and executing Password Policies.
PasswordPolicyUITestCase Test case to verify accuracy of each available policy condition.