You are here

class AcquiaSearchTest in Acquia Connector 8

Isolated tests for Acquia Search.

@coversDefaultClass \Drupal\acquia_search\EventSubscriber\SearchSubscriber

@group Acquia search

Hierarchy

Expanded class hierarchy of AcquiaSearchTest

File

acquia_search/tests/src/Unit/AcquiaSearchTest.php, line 16

Namespace

Drupal\Tests\acquia_search\Unit
View source
class AcquiaSearchTest extends UnitTestCase {

  /**
   * Acquia subscription ID.
   *
   * @var string
   */
  protected $id;

  /**
   * Key.
   *
   * @var string
   */
  protected $key;

  /**
   * Salt.
   *
   * @var string
   */
  protected $salt;

  /**
   * Derived key.
   *
   * @var string
   */
  protected $derivedKey;

  /**
   * Search subscriber.
   *
   * @var \Drupal\acquia_search\EventSubscriber\SearchSubscriber
   */
  protected $searchSubscriber;

  /**
   * {@inheritdoc}
   */
  protected function setUp() {

    // Generate and store a random set of credentials.
    // Make them as close to the production values as possible
    // Something like AAAA-1234.
    $this->id = $this
      ->randomMachineName(10);

    // Most of the keys and salts have a 32char length.
    $this->key = $this
      ->randomMachineName(32);
    $this->salt = $this
      ->randomMachineName(32);

    // Include Solarium autoloader.
    $dirs = drupal_phpunit_contrib_extension_directory_roots();
    $extensions = [];
    foreach ($dirs as $path) {
      $extensions += drupal_phpunit_find_extension_directories($path);
    }
    unset($extensions);
    $this->searchSubscriber = new SearchSubscriber();
    $this->derivedKey = CryptConnector::createDerivedKey($this->salt, $this->id, $this->key);
  }

  /**
   * Check createDerivedKey.
   */
  public function testCreateDerivedKey() {

    // Mimic the hashing code in the API function.
    $derivation_string = $this->id . 'solr' . $this->salt;

    // str_pad extends the string with the same string in this case
    // until it has filled 80 chars.
    $derived_key = hash_hmac('sha1', str_pad($derivation_string, 80, $derivation_string), $this->key);

    // $this->derivedKey is generated from the API function.
    // @see setUp()
    $this
      ->assertEquals($derived_key, $this->derivedKey);
  }

  /**
   * Covers calculateAuthCookie.
   *
   * @covers ::calculateAuthCookie
   */
  public function testCalculateAuthCookie() {

    // Generate the expected hash.
    $time = 1577635946;
    $nonce = $this
      ->randomMachineName(32);
    $string = $time . $nonce . $this
      ->randomMachineName();
    $hmac = hash_hmac('sha1', $time . $nonce . $string, $this->derivedKey);
    $calculateAuthCookie = $this
      ->getMockBuilder('Drupal\\acquia_search\\EventSubscriber\\SearchSubscriber')
      ->setMethods([
      'getDerivedKey',
    ])
      ->getMock();
    $calculateAuthCookie
      ->expects($this
      ->any())
      ->method('getDerivedKey')
      ->willReturn($this->derivedKey);
    $authenticator = $calculateAuthCookie
      ->calculateAuthCookie($string, $nonce, $time, $this->derivedKey, $time);
    preg_match('/acquia_solr_hmac=([a-zA-Z0-9]{40});/', $authenticator, $matches);
    $this
      ->assertEquals($hmac, $matches[1], 'HMAC API function generates the expected hmac hash.');
    preg_match('/acquia_solr_time=([0-9]{10});/', $authenticator, $matches);
    $this
      ->assertNotNull($matches, 'HMAC API function generates a timestamp.', 'Acquia Search');
    preg_match('/acquia_solr_nonce=([a-zA-Z0-9]{32});/', $authenticator, $matches);
    $this
      ->assertEquals($nonce, $matches[1], 'HMAC API function generates the expected nonce.');
  }

  /**
   * Covers validateResponse.
   *
   * @covers ::validateResponse
   */
  public function testValidResponse() {

    // Generate the expected hash.
    $nonce = $this
      ->randomMachineName(32);
    $string = $this
      ->randomMachineName(32);
    $hmac = hash_hmac('sha1', $nonce . $string, $this->derivedKey);

    // Pass the expected hmac digest, API function should return TRUE.
    $valid = $this->searchSubscriber
      ->validateResponse($hmac, $nonce, $string, $this->derivedKey);
    $this
      ->assertTrue($valid, 'Response flagged as valid when the expected hash is passed.');

    // Invalidate the hmac digest, API function should return FALSE.
    $bad_hmac = $hmac . 'invalidateHash';
    $invalid_hmac = $this->searchSubscriber
      ->validateResponse($bad_hmac, $nonce, $string, $this->derivedKey);
    $this
      ->assertFalse($invalid_hmac, 'Response flagged as invalid when a malformed hash is passed.');

    // Invalidate the nonce, API function should return FALSE.
    $bad_nonce = $nonce . 'invalidateString';
    $invalid_nonce = $this->searchSubscriber
      ->validateResponse($hmac, $bad_nonce, $string, $this->derivedKey);
    $this
      ->assertFalse($invalid_nonce, 'Response flagged as invalid when a malformed nonce is passed.');

    // Invalidate the string, API function should return FALSE.
    $bad_string = $string . 'invalidateString';
    $invalid_string = $this->searchSubscriber
      ->validateResponse($hmac, $nonce, $bad_string, $this->derivedKey);
    $this
      ->assertFalse($invalid_string, 'Response flagged as invalid when a malformed string is passed.');

    // Invalidate the derived key, API function should return FALSE.
    $bad_key = $this->derivedKey . 'invalidateKey';
    $invalid_key = $this->searchSubscriber
      ->validateResponse($hmac, $nonce, $string, $bad_key);
    $this
      ->assertFalse($invalid_key, 'Response flagged as invalid when a malformed derived key is passed.');
  }

  /**
   * Covers extractHmac.
   *
   * @covers ::extractHmac
   */
  public function testExtractHmacHeader() {

    // Generate the expected hash.
    $nonce = $this
      ->randomMachineName(32);
    $string = $this
      ->randomMachineName(32);
    $hmac = hash_hmac('sha1', $nonce . $string, $this->derivedKey);

    // Pass header with an expected pragma.
    $headers = [
      'pragma/hmac_digest=' . $hmac . ';',
    ];
    $extracted = $this->searchSubscriber
      ->extractHmac($headers);
    $this
      ->assertEquals($hmac, $extracted, 'The HMAC digest was extracted from the response header.');

    // Pass header with a bad pragma.
    $bad_headers1 = [
      'pragma/' . $this
        ->randomMachineName(),
    ];
    $bad_extracted1 = $this->searchSubscriber
      ->extractHmac($bad_headers1);
    $this
      ->assertEquals('', $bad_extracted1, 'Empty string returned by HMAC extraction function when an invalid pragma is passed.');

    // Pass in junk as the header.
    $bad_extracted2 = $this->searchSubscriber
      ->extractHmac($this
      ->randomMachineName());
    $this
      ->assertEquals('', $bad_extracted2, 'Empty string returned by HMAC extraction function when an invalid header is passed.');
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AcquiaSearchTest::$derivedKey protected property Derived key.
AcquiaSearchTest::$id protected property Acquia subscription ID.
AcquiaSearchTest::$key protected property Key.
AcquiaSearchTest::$salt protected property Salt.
AcquiaSearchTest::$searchSubscriber protected property Search subscriber.
AcquiaSearchTest::setUp protected function Overrides UnitTestCase::setUp
AcquiaSearchTest::testCalculateAuthCookie public function Covers calculateAuthCookie.
AcquiaSearchTest::testCreateDerivedKey public function Check createDerivedKey.
AcquiaSearchTest::testExtractHmacHeader public function Covers extractHmac.
AcquiaSearchTest::testValidResponse public function Covers validateResponse.
PhpunitCompatibilityTrait::getMock Deprecated public function Returns a mock object for the specified class using the available method.
PhpunitCompatibilityTrait::setExpectedException Deprecated public function Compatibility layer for PHPUnit 6 to support PHPUnit 4 code.
UnitTestCase::$randomGenerator protected property The random generator.
UnitTestCase::$root protected property The app root. 1
UnitTestCase::assertArrayEquals protected function Asserts if two arrays are equal by sorting them first.
UnitTestCase::getBlockMockWithMachineName Deprecated protected function Mocks a block with a block plugin. 1
UnitTestCase::getClassResolverStub protected function Returns a stub class resolver.
UnitTestCase::getConfigFactoryStub public function Returns a stub config factory that behaves according to the passed array.
UnitTestCase::getConfigStorageStub public function Returns a stub config storage that returns the supplied configuration.
UnitTestCase::getContainerWithCacheTagsInvalidator protected function Sets up a container with a cache tags invalidator.
UnitTestCase::getRandomGenerator protected function Gets the random generator for the utility methods.
UnitTestCase::getStringTranslationStub public function Returns a stub translation manager that just returns the passed string.
UnitTestCase::randomMachineName public function Generates a unique random string containing letters and numbers.