From 6c5130d0c12ed72fa7addca22a6dc0c3b767caca Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Mon, 28 Jul 2014 22:49:42 +0100 Subject: [PATCH] Issue #2008566 by kim.pepper, jhedstrom, Berdir: Convert PasswordHashingTest unit tests to phpunit. --- .../src/Tests/System/PasswordHashingTest.php | 61 ------- .../Core/Password/PasswordHashingTest.php | 156 ++++++++++++++++++ 2 files changed, 156 insertions(+), 61 deletions(-) delete mode 100644 core/modules/system/src/Tests/System/PasswordHashingTest.php create mode 100644 core/tests/Drupal/Tests/Core/Password/PasswordHashingTest.php diff --git a/core/modules/system/src/Tests/System/PasswordHashingTest.php b/core/modules/system/src/Tests/System/PasswordHashingTest.php deleted file mode 100644 index b3c7aad703bc..000000000000 --- a/core/modules/system/src/Tests/System/PasswordHashingTest.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/** - * @file - * Definition of Drupal\system\Tests\System\PasswordHashingTest. - */ - -namespace Drupal\system\Tests\System; - -use Drupal\simpletest\DrupalUnitTestBase; -use Drupal\Core\Password\PhpassHashedPassword; - -/** - * Password hashing unit tests. - * - * @group system - */ -class PasswordHashingTest extends DrupalUnitTestBase { - - /** - * Modules to enable. - * - * @var array - */ - public static $modules = array('field', 'user'); - - /** - * Test password hashing. - */ - function testPasswordHashing() { - // Set a log2 iteration count that is deliberately out of bounds to test - // that it is corrected to be within bounds. - $password_hasher = new PhpassHashedPassword(1); - // Set up a fake $account with a password 'baz', hashed with md5. - $password = 'baz'; - $account = entity_create('user', array('name' => 'foo', 'pass' => md5($password))); - // The md5 password should be flagged as needing an update. - $this->assertTrue($password_hasher->userNeedsNewHash($account), 'User with md5 password needs a new hash.'); - // Re-hash the password. - $old_hash = $account->getPassword(); - $account->setPassword($password_hasher->hash($password)); - $this->assertIdentical($password_hasher->getCountLog2($account->getPassword()), $password_hasher::MIN_HASH_COUNT, 'Re-hashed password has the minimum number of log2 iterations.'); - $this->assertTrue($account->getPassword() != $old_hash, 'Password hash changed.'); - $this->assertTrue($password_hasher->check($password, $account), 'Password check succeeds.'); - // Since the log2 setting hasn't changed and the user has a valid password, - // $password_hasher->userNeedsNewHash() should return FALSE. - $this->assertFalse($password_hasher->userNeedsNewHash($account), 'User does not need a new hash.'); - - // Increment the log2 iteration to MIN + 1. - $password_hasher = new PhpassHashedPassword($password_hasher::MIN_HASH_COUNT + 1); - $this->assertTrue($password_hasher->userNeedsNewHash($account), 'User needs a new hash after incrementing the log2 count.'); - // Re-hash the password. - $old_hash = $account->getPassword(); - $account->setPassword($password_hasher->hash($password)); - $this->assertIdentical($password_hasher->getCountLog2($account->getPassword()), $password_hasher::MIN_HASH_COUNT + 1, 'Re-hashed password has the correct number of log2 iterations.'); - $this->assertTrue($account->getPassword() != $old_hash, 'Password hash changed again.'); - // Now the hash should be OK. - $this->assertFalse($password_hasher->userNeedsNewHash($account), 'Re-hashed password does not need a new hash.'); - $this->assertTrue($password_hasher->check($password, $account), 'Password check succeeds with re-hashed password.'); - } -} diff --git a/core/tests/Drupal/Tests/Core/Password/PasswordHashingTest.php b/core/tests/Drupal/Tests/Core/Password/PasswordHashingTest.php new file mode 100644 index 000000000000..bdae80686715 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Password/PasswordHashingTest.php @@ -0,0 +1,156 @@ +<?php + +/** + * @file + * Contains Drupal\system\Tests\System\PasswordHashingTest. + */ + +namespace Drupal\Tests\Core\Password; + +use Drupal\Core\Password\PhpassHashedPassword; +use Drupal\Tests\UnitTestCase; + +/** + * Unit tests for password hashing API. + * + * @coversDefaultClass \Drupal\Core\Password\PhpassHashedPassword + * @group System + */ +class PasswordHashingTest extends UnitTestCase { + + /** + * The user for testing. + * + * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\user\UserInterface + */ + protected $user; + + /** + * The raw password. + * + * @var string + */ + protected $password; + + /** + * The md5 password. + * + * @var string + */ + protected $md5Password; + + /** + * The hashed password. + * + * @var string + */ + protected $hashedPassword; + + /** + * The password hasher under test. + * + * @var \Drupal\Core\Password\PhpassHashedPassword + */ + protected $passwordHasher; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->user = $this->getMockBuilder('Drupal\user\Entity\User') + ->disableOriginalConstructor() + ->getMock(); + $this->passwordHasher = new PhpassHashedPassword(1); + } + + /** + * Tests the hash count boundaries are enforced. + * + * @covers ::enforceLog2Boundaries + */ + public function testWithinBounds() { + $hasher = new FakePhpassHashedPassword(); + $this->assertEquals(PhpassHashedPassword::MIN_HASH_COUNT, $hasher->enforceLog2Boundaries(1), "Min hash count enforced"); + $this->assertEquals(PhpassHashedPassword::MAX_HASH_COUNT, $hasher->enforceLog2Boundaries(100), "Max hash count enforced"); + } + + + /** + * Test a password needs update. + * + * @covers ::userNeedsNewHash + */ + public function testPasswordNeedsUpdate() { + $this->user->expects($this->any()) + ->method('getPassword') + ->will($this->returnValue($this->md5Password)); + // The md5 password should be flagged as needing an update. + $this->assertTrue($this->passwordHasher->userNeedsNewHash($this->user), 'User with md5 password needs a new hash.'); + } + + /** + * Test password hashing. + * + * @covers ::hash + * @covers ::getCountLog2 + * @covers ::check + * @covers ::userNeedsNewHash + */ + public function testPasswordHashing() { + $this->hashedPassword = $this->passwordHasher->hash($this->password); + $this->user->expects($this->any()) + ->method('getPassword') + ->will($this->returnValue($this->hashedPassword)); + $this->assertSame($this->passwordHasher->getCountLog2($this->hashedPassword), PhpassHashedPassword::MIN_HASH_COUNT, 'Hashed password has the minimum number of log2 iterations.'); + $this->assertNotEquals($this->hashedPassword, $this->md5Password, 'Password hash changed.'); + $this->assertTrue($this->passwordHasher->check($this->password, $this->user), 'Password check succeeds.'); + // Since the log2 setting hasn't changed and the user has a valid password, + // userNeedsNewHash() should return FALSE. + $this->assertFalse($this->passwordHasher->userNeedsNewHash($this->user), 'User does not need a new hash.'); + } + + /** + * Tests password rehashing. + * + * @covers ::hash + * @covers ::getCountLog2 + * @covers ::check + * @covers ::userNeedsNewHash + */ + public function testPasswordRehashing() { + + // Increment the log2 iteration to MIN + 1. + $this->passwordHasher = new PhpassHashedPassword(PhpassHashedPassword::MIN_HASH_COUNT + 1); + $this->assertTrue($this->passwordHasher->userNeedsNewHash($this->user), 'User needs a new hash after incrementing the log2 count.'); + // Re-hash the password. + $rehashed_password = $this->passwordHasher->hash($this->password); + + $this->user->expects($this->any()) + ->method('getPassword') + ->will($this->returnValue($rehashed_password)); + $this->assertSame($this->passwordHasher->getCountLog2($rehashed_password), PhpassHashedPassword::MIN_HASH_COUNT + 1, 'Re-hashed password has the correct number of log2 iterations.'); + $this->assertNotEquals($rehashed_password, $this->hashedPassword, 'Password hash changed again.'); + + // Now the hash should be OK. + $this->assertFalse($this->passwordHasher->userNeedsNewHash($this->user), 'Re-hashed password does not need a new hash.'); + $this->assertTrue($this->passwordHasher->check($this->password, $this->user), 'Password check succeeds with re-hashed password.'); + } + +} + +/** + * A fake class for tests. + */ +class FakePhpassHashedPassword extends PhpassHashedPassword { + + function __construct() { + // Noop. + } + + // Expose this method as public for tests. + public function enforceLog2Boundaries($count_log2) { + return parent::enforceLog2Boundaries($count_log2); + } + +} -- GitLab