Version 1
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Path / AliasManagerTest.php
diff --git a/web/core/tests/Drupal/Tests/Core/Path/AliasManagerTest.php b/web/core/tests/Drupal/Tests/Core/Path/AliasManagerTest.php
new file mode 100644 (file)
index 0000000..ffd52dc
--- /dev/null
@@ -0,0 +1,548 @@
+<?php
+
+namespace Drupal\Tests\Core\Path;
+
+use Drupal\Core\Language\Language;
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\Path\AliasManager;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Path\AliasManager
+ * @group Path
+ */
+class AliasManagerTest extends UnitTestCase {
+
+  /**
+   * The alias manager.
+   *
+   * @var \Drupal\Core\Path\AliasManager
+   */
+  protected $aliasManager;
+
+  /**
+   * Alias storage.
+   *
+   * @var \Drupal\Core\Path\AliasStorageInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $aliasStorage;
+
+  /**
+   * Alias whitelist.
+   *
+   * @var \Drupal\Core\Path\AliasWhitelistInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $aliasWhitelist;
+
+  /**
+   * Language manager.
+   *
+   * @var \Drupal\Core\Language\LanguageManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $languageManager;
+
+  /**
+   * Cache backend.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cache;
+
+  /**
+   * The internal cache key used by the alias manager.
+   *
+   * @var string
+   */
+  protected $cacheKey = 'preload-paths:key';
+
+  /**
+   * The cache key passed to the alias manager.
+   *
+   * @var string
+   */
+  protected $path = 'key';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->aliasStorage = $this->getMock('Drupal\Core\Path\AliasStorageInterface');
+    $this->aliasWhitelist = $this->getMock('Drupal\Core\Path\AliasWhitelistInterface');
+    $this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
+    $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+
+    $this->aliasManager = new AliasManager($this->aliasStorage, $this->aliasWhitelist, $this->languageManager, $this->cache);
+
+  }
+
+  /**
+   * Tests the getPathByAlias method for an alias that have no matching path.
+   *
+   * @covers ::getPathByAlias
+   */
+  public function testGetPathByAliasNoMatch() {
+    $alias = '/' . $this->randomMachineName();
+
+    $language = new Language(['id' => 'en']);
+
+    $this->languageManager->expects($this->any())
+      ->method('getCurrentLanguage')
+      ->with(LanguageInterface::TYPE_URL)
+      ->will($this->returnValue($language));
+
+    $this->aliasStorage->expects($this->once())
+      ->method('lookupPathSource')
+      ->with($alias, $language->getId())
+      ->will($this->returnValue(NULL));
+
+    $this->assertEquals($alias, $this->aliasManager->getPathByAlias($alias));
+    // Call it twice to test the static cache.
+    $this->assertEquals($alias, $this->aliasManager->getPathByAlias($alias));
+  }
+
+  /**
+   * Tests the getPathByAlias method for an alias that have a matching path.
+   *
+   * @covers ::getPathByAlias
+   */
+  public function testGetPathByAliasNatch() {
+    $alias = $this->randomMachineName();
+    $path = $this->randomMachineName();
+
+    $language = $this->setUpCurrentLanguage();
+
+    $this->aliasStorage->expects($this->once())
+      ->method('lookupPathSource')
+      ->with($alias, $language->getId())
+      ->will($this->returnValue($path));
+
+    $this->assertEquals($path, $this->aliasManager->getPathByAlias($alias));
+    // Call it twice to test the static cache.
+    $this->assertEquals($path, $this->aliasManager->getPathByAlias($alias));
+  }
+
+  /**
+   * Tests the getPathByAlias method when a langcode is passed explicitly.
+   *
+   * @covers ::getPathByAlias
+   */
+  public function testGetPathByAliasLangcode() {
+    $alias = $this->randomMachineName();
+    $path = $this->randomMachineName();
+
+    $this->languageManager->expects($this->never())
+      ->method('getCurrentLanguage');
+
+    $this->aliasStorage->expects($this->once())
+      ->method('lookupPathSource')
+      ->with($alias, 'de')
+      ->will($this->returnValue($path));
+
+    $this->assertEquals($path, $this->aliasManager->getPathByAlias($alias, 'de'));
+    // Call it twice to test the static cache.
+    $this->assertEquals($path, $this->aliasManager->getPathByAlias($alias, 'de'));
+  }
+
+
+  /**
+   * Tests the getAliasByPath method for a path that is not in the whitelist.
+   *
+   * @covers ::getAliasByPath
+   */
+  public function testGetAliasByPathWhitelist() {
+    $path_part1 = $this->randomMachineName();
+    $path_part2 = $this->randomMachineName();
+    $path = '/' . $path_part1 . '/' . $path_part2;
+
+    $this->setUpCurrentLanguage();
+
+    $this->aliasWhitelist->expects($this->any())
+      ->method('get')
+      ->with($path_part1)
+      ->will($this->returnValue(FALSE));
+
+    // The whitelist returns FALSE for that path part, so the storage should
+    // never be called.
+    $this->aliasStorage->expects($this->never())
+      ->method('lookupPathAlias');
+
+    $this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
+  }
+
+  /**
+   * Tests the getAliasByPath method for a path that has no matching alias.
+   *
+   * @covers ::getAliasByPath
+   */
+  public function testGetAliasByPathNoMatch() {
+    $path_part1 = $this->randomMachineName();
+    $path_part2 = $this->randomMachineName();
+    $path = '/' . $path_part1 . '/' . $path_part2;
+
+    $language = $this->setUpCurrentLanguage();
+
+    $this->aliasManager->setCacheKey($this->path);
+
+    $this->aliasWhitelist->expects($this->any())
+      ->method('get')
+      ->with($path_part1)
+      ->will($this->returnValue(TRUE));
+
+    $this->aliasStorage->expects($this->once())
+      ->method('lookupPathAlias')
+      ->with($path, $language->getId())
+      ->will($this->returnValue(NULL));
+
+    $this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
+    // Call it twice to test the static cache.
+    $this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
+
+    // This needs to write out the cache.
+    $this->cache->expects($this->once())
+      ->method('set')
+      ->with($this->cacheKey, [$language->getId() => [$path]], (int) $_SERVER['REQUEST_TIME'] + (60 * 60 * 24));
+
+    $this->aliasManager->writeCache();
+  }
+
+  /**
+   * Tests the getAliasByPath method for a path that has a matching alias.
+   *
+   * @covers ::getAliasByPath
+   * @covers ::writeCache
+   */
+  public function testGetAliasByPathMatch() {
+    $path_part1 = $this->randomMachineName();
+    $path_part2 = $this->randomMachineName();
+    $path = '/' . $path_part1 . '/' . $path_part2;
+    $alias = $this->randomMachineName();
+
+    $language = $this->setUpCurrentLanguage();
+
+    $this->aliasManager->setCacheKey($this->path);
+
+    $this->aliasWhitelist->expects($this->any())
+      ->method('get')
+      ->with($path_part1)
+      ->will($this->returnValue(TRUE));
+
+    $this->aliasStorage->expects($this->once())
+      ->method('lookupPathAlias')
+      ->with($path, $language->getId())
+      ->will($this->returnValue($alias));
+
+    $this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
+    // Call it twice to test the static cache.
+    $this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
+
+    // This needs to write out the cache.
+    $this->cache->expects($this->once())
+      ->method('set')
+      ->with($this->cacheKey, [$language->getId() => [$path]], (int) $_SERVER['REQUEST_TIME'] + (60 * 60 * 24));
+
+    $this->aliasManager->writeCache();
+  }
+
+  /**
+   * Tests the getAliasByPath method for a path that is preloaded.
+   *
+   * @covers ::getAliasByPath
+   * @covers ::writeCache
+   */
+  public function testGetAliasByPathCachedMatch() {
+    $path_part1 = $this->randomMachineName();
+    $path_part2 = $this->randomMachineName();
+    $path = '/' . $path_part1 . '/' . $path_part2;
+    $alias = $this->randomMachineName();
+
+    $language = $this->setUpCurrentLanguage();
+
+    $cached_paths = [$language->getId() => [$path]];
+    $this->cache->expects($this->once())
+      ->method('get')
+      ->with($this->cacheKey)
+      ->will($this->returnValue((object) ['data' => $cached_paths]));
+
+    // Simulate a request so that the preloaded paths are fetched.
+    $this->aliasManager->setCacheKey($this->path);
+
+    $this->aliasWhitelist->expects($this->any())
+      ->method('get')
+      ->with($path_part1)
+      ->will($this->returnValue(TRUE));
+
+    $this->aliasStorage->expects($this->once())
+      ->method('preloadPathAlias')
+      ->with($cached_paths[$language->getId()], $language->getId())
+      ->will($this->returnValue([$path => $alias]));
+
+    // LookupPathAlias should not be called.
+    $this->aliasStorage->expects($this->never())
+      ->method('lookupPathAlias');
+
+    $this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
+    // Call it twice to test the static cache.
+    $this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
+
+    // This must not write to the cache again.
+    $this->cache->expects($this->never())
+      ->method('set');
+    $this->aliasManager->writeCache();
+  }
+
+  /**
+   * Tests the getAliasByPath cache when a different language is requested.
+   *
+   * @covers ::getAliasByPath
+   * @covers ::writeCache
+   */
+  public function testGetAliasByPathCachedMissLanguage() {
+    $path_part1 = $this->randomMachineName();
+    $path_part2 = $this->randomMachineName();
+    $path = '/' . $path_part1 . '/' . $path_part2;
+    $alias = $this->randomMachineName();
+
+    $language = $this->setUpCurrentLanguage();
+    $cached_language = new Language(['id' => 'de']);
+
+    $cached_paths = [$cached_language->getId() => [$path]];
+    $this->cache->expects($this->once())
+      ->method('get')
+      ->with($this->cacheKey)
+      ->will($this->returnValue((object) ['data' => $cached_paths]));
+
+    // Simulate a request so that the preloaded paths are fetched.
+    $this->aliasManager->setCacheKey($this->path);
+
+    $this->aliasWhitelist->expects($this->any())
+      ->method('get')
+      ->with($path_part1)
+      ->will($this->returnValue(TRUE));
+
+    // The requested language is different than the cached, so this will
+    // need to load.
+    $this->aliasStorage->expects($this->never())
+      ->method('preloadPathAlias');
+    $this->aliasStorage->expects($this->once())
+      ->method('lookupPathAlias')
+      ->with($path, $language->getId())
+      ->will($this->returnValue($alias));
+
+    $this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
+    // Call it twice to test the static cache.
+    $this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
+
+    // There is already a cache entry, so this should not write out to the
+    // cache.
+    $this->cache->expects($this->never())
+      ->method('set');
+    $this->aliasManager->writeCache();
+  }
+
+  /**
+   * Tests the getAliasByPath cache with a preloaded path without alias.
+   *
+   * @covers ::getAliasByPath
+   * @covers ::writeCache
+   */
+  public function testGetAliasByPathCachedMissNoAlias() {
+    $path_part1 = $this->randomMachineName();
+    $path_part2 = $this->randomMachineName();
+    $path = '/' . $path_part1 . '/' . $path_part2;
+    $cached_path = $this->randomMachineName();
+    $cached_alias = $this->randomMachineName();
+
+    $language = $this->setUpCurrentLanguage();
+
+    $cached_paths = [$language->getId() => [$cached_path, $path]];
+    $this->cache->expects($this->once())
+      ->method('get')
+      ->with($this->cacheKey)
+      ->will($this->returnValue((object) ['data' => $cached_paths]));
+
+    // Simulate a request so that the preloaded paths are fetched.
+    $this->aliasManager->setCacheKey($this->path);
+
+    $this->aliasWhitelist->expects($this->any())
+      ->method('get')
+      ->with($path_part1)
+      ->will($this->returnValue(TRUE));
+
+    $this->aliasStorage->expects($this->once())
+      ->method('preloadPathAlias')
+      ->with($cached_paths[$language->getId()], $language->getId())
+      ->will($this->returnValue([$cached_path => $cached_alias]));
+
+    // LookupPathAlias() should not be called.
+    $this->aliasStorage->expects($this->never())
+      ->method('lookupPathAlias');
+
+    $this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
+    // Call it twice to test the static cache.
+    $this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
+
+    // This must not write to the cache again.
+    $this->cache->expects($this->never())
+      ->method('set');
+    $this->aliasManager->writeCache();
+  }
+
+  /**
+   * Tests the getAliasByPath cache with an unpreloaded path without alias.
+   *
+   * @covers ::getAliasByPath
+   * @covers ::writeCache
+   */
+  public function testGetAliasByPathUncachedMissNoAlias() {
+    $path_part1 = $this->randomMachineName();
+    $path_part2 = $this->randomMachineName();
+    $path = '/' . $path_part1 . '/' . $path_part2;
+    $cached_path = $this->randomMachineName();
+    $cached_alias = $this->randomMachineName();
+
+    $language = $this->setUpCurrentLanguage();
+
+    $cached_paths = [$language->getId() => [$cached_path]];
+    $this->cache->expects($this->once())
+      ->method('get')
+      ->with($this->cacheKey)
+      ->will($this->returnValue((object) ['data' => $cached_paths]));
+
+    // Simulate a request so that the preloaded paths are fetched.
+    $this->aliasManager->setCacheKey($this->path);
+
+    $this->aliasWhitelist->expects($this->any())
+      ->method('get')
+      ->with($path_part1)
+      ->will($this->returnValue(TRUE));
+
+    $this->aliasStorage->expects($this->once())
+      ->method('preloadPathAlias')
+      ->with($cached_paths[$language->getId()], $language->getId())
+      ->will($this->returnValue([$cached_path => $cached_alias]));
+
+    $this->aliasStorage->expects($this->once())
+      ->method('lookupPathAlias')
+      ->with($path, $language->getId())
+      ->will($this->returnValue(NULL));
+
+    $this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
+    // Call it twice to test the static cache.
+    $this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
+
+    // There is already a cache entry, so this should not write out to the
+    // cache.
+    $this->cache->expects($this->never())
+      ->method('set');
+    $this->aliasManager->writeCache();
+  }
+
+  /**
+   * @covers ::cacheClear
+   */
+  public function testCacheClear() {
+    $path = '/path';
+    $alias = '/alias';
+    $language = $this->setUpCurrentLanguage();
+    $this->aliasStorage->expects($this->exactly(2))
+      ->method('lookupPathAlias')
+      ->with($path, $language->getId())
+      ->willReturn($alias);
+    $this->aliasWhitelist->expects($this->any())
+      ->method('get')
+      ->willReturn(TRUE);
+
+    // Populate the lookup map.
+    $this->assertEquals($alias, $this->aliasManager->getAliasByPath($path, $language->getId()));
+
+    // Check that the cache is populated.
+    $original_storage = clone $this->aliasStorage;
+    $this->aliasStorage->expects($this->never())
+      ->method('lookupPathSource');
+    $this->assertEquals($path, $this->aliasManager->getPathByAlias($alias, $language->getId()));
+
+    // Clear specific source.
+    $this->cache->expects($this->exactly(2))
+      ->method('delete');
+    $this->aliasManager->cacheClear($path);
+
+    // Ensure cache has been cleared (this will be the 2nd call to
+    // `lookupPathAlias` if cache is cleared).
+    $this->assertEquals($alias, $this->aliasManager->getAliasByPath($path, $language->getId()));
+
+    // Clear non-existent source.
+    $this->aliasManager->cacheClear('non-existent');
+  }
+
+  /**
+   * Tests the getAliasByPath cache with an unpreloaded path with alias.
+   *
+   * @covers ::getAliasByPath
+   * @covers ::writeCache
+   */
+  public function testGetAliasByPathUncachedMissWithAlias() {
+    $path_part1 = $this->randomMachineName();
+    $path_part2 = $this->randomMachineName();
+    $path = '/' . $path_part1 . '/' . $path_part2;
+    $cached_path = $this->randomMachineName();
+    $cached_no_alias_path = $this->randomMachineName();
+    $cached_alias = $this->randomMachineName();
+    $new_alias = $this->randomMachineName();
+
+    $language = $this->setUpCurrentLanguage();
+
+    $cached_paths = [$language->getId() => [$cached_path, $cached_no_alias_path]];
+    $this->cache->expects($this->once())
+      ->method('get')
+      ->with($this->cacheKey)
+      ->will($this->returnValue((object) ['data' => $cached_paths]));
+
+    // Simulate a request so that the preloaded paths are fetched.
+    $this->aliasManager->setCacheKey($this->path);
+
+    $this->aliasWhitelist->expects($this->any())
+      ->method('get')
+      ->with($path_part1)
+      ->will($this->returnValue(TRUE));
+
+    $this->aliasStorage->expects($this->once())
+      ->method('preloadPathAlias')
+      ->with($cached_paths[$language->getId()], $language->getId())
+      ->will($this->returnValue([$cached_path => $cached_alias]));
+
+    $this->aliasStorage->expects($this->once())
+      ->method('lookupPathAlias')
+      ->with($path, $language->getId())
+      ->will($this->returnValue($new_alias));
+
+    $this->assertEquals($new_alias, $this->aliasManager->getAliasByPath($path));
+    // Call it twice to test the static cache.
+    $this->assertEquals($new_alias, $this->aliasManager->getAliasByPath($path));
+
+    // There is already a cache entry, so this should not write out to the
+    // cache.
+    $this->cache->expects($this->never())
+      ->method('set');
+    $this->aliasManager->writeCache();
+  }
+
+  /**
+   * Sets up the current language.
+   *
+   * @return \Drupal\Core\Language\LanguageInterface
+   *   The current language object.
+   */
+  protected function setUpCurrentLanguage() {
+    $language = new Language(['id' => 'en']);
+
+    $this->languageManager->expects($this->any())
+      ->method('getCurrentLanguage')
+      ->with(LanguageInterface::TYPE_URL)
+      ->will($this->returnValue($language));
+
+    return $language;
+  }
+
+}