class AccessPolicyProcessorTest
Same name in other branches
- 11.x core/tests/Drupal/Tests/Core/Session/AccessPolicyProcessorTest.php \Drupal\Tests\Core\Session\AccessPolicyProcessorTest
Tests the AccessPolicyProcessor service.
@covers \Drupal\Core\Session\AccessPolicyBase @covers \Drupal\Core\Session\AccessPolicyProcessor @group Session
Hierarchy
- class \Drupal\Tests\UnitTestCase extends \PHPUnit\Framework\TestCase uses \Drupal\Tests\Traits\PhpUnitWarnings, \Drupal\Tests\PhpUnitCompatibilityTrait, \Prophecy\PhpUnit\ProphecyTrait, \Symfony\Bridge\PhpUnit\ExpectDeprecationTrait, \Drupal\Tests\RandomGeneratorTrait
- class \Drupal\Tests\Core\Session\AccessPolicyProcessorTest extends \Drupal\Tests\UnitTestCase
Expanded class hierarchy of AccessPolicyProcessorTest
File
-
core/
tests/ Drupal/ Tests/ Core/ Session/ AccessPolicyProcessorTest.php, line 32
Namespace
Drupal\Tests\Core\SessionView source
class AccessPolicyProcessorTest extends UnitTestCase {
/**
* {@inheritdoc}
*/
public function setUp() : void {
parent::setUp();
$cache_context_manager = $this->prophesize(CacheContextsManager::class);
$cache_context_manager->assertValidTokens(Argument::any())
->willReturn(TRUE);
$container = $this->prophesize(ContainerInterface::class);
$container->get('cache_contexts_manager')
->willReturn($cache_context_manager->reveal());
\Drupal::setContainer($container->reveal());
}
/**
* Tests that access policies are properly processed.
*/
public function testCalculatePermissions() : void {
$account = $this->prophesize(AccountInterface::class)
->reveal();
$access_policy = new BarAccessPolicy();
$processor = $this->setUpAccessPolicyProcessor();
$processor->addAccessPolicy($access_policy);
$access_policy_permissions = $access_policy->calculatePermissions($account, 'bar');
$access_policy_permissions->addCacheTags([
'access_policies',
]);
$this->assertEquals(new CalculatedPermissions($access_policy_permissions), $processor->processAccessPolicies($account, 'bar'));
}
/**
* Tests that access policies that do not apply are not processed.
*/
public function testCalculatePermissionsNoApply() : void {
$account = $this->prophesize(AccountInterface::class)
->reveal();
$access_policy = new BarAccessPolicy();
$processor = $this->setUpAccessPolicyProcessor();
$processor->addAccessPolicy($access_policy);
$no_permissions = new RefinableCalculatedPermissions();
$no_permissions->addCacheTags([
'access_policies',
]);
$calculated_permissions = $processor->processAccessPolicies($account, 'nothing');
$this->assertEquals(new CalculatedPermissions($no_permissions), $calculated_permissions);
}
/**
* Tests that access policies can alter the final result.
*/
public function testAlterPermissions() : void {
$account = $this->prophesize(AccountInterface::class)
->reveal();
$processor = $this->setUpAccessPolicyProcessor();
$processor->addAccessPolicy(new BarAccessPolicy());
$processor->addAccessPolicy(new BarAlterAccessPolicy());
$actual_permissions = $processor->processAccessPolicies($account, 'bar')
->getItem('bar', 1)
->getPermissions();
$this->assertEquals([
'foo',
'baz',
], $actual_permissions);
}
/**
* Tests that alters that do not apply are not processed.
*/
public function testAlterPermissionsNoApply() : void {
$account = $this->prophesize(AccountInterface::class)
->reveal();
$processor = $this->setUpAccessPolicyProcessor();
$processor->addAccessPolicy($access_policy = new FooAccessPolicy());
$processor->addAccessPolicy(new BarAlterAccessPolicy());
$access_policy_permissions = $access_policy->calculatePermissions($account, 'foo');
$access_policy_permissions->addCacheTags([
'access_policies',
]);
$this->assertEquals(new CalculatedPermissions($access_policy_permissions), $processor->processAccessPolicies($account, 'foo'));
}
/**
* Tests that access policies which do nothing are properly processed.
*/
public function testEmptyCalculator() : void {
$account = $this->prophesize(AccountInterface::class)
->reveal();
$access_policy = new EmptyAccessPolicy();
$processor = $this->setUpAccessPolicyProcessor();
$processor->addAccessPolicy($access_policy);
$access_policy_permissions = $access_policy->calculatePermissions($account, 'anything');
$access_policy_permissions->addCacheTags([
'access_policies',
]);
$calculated_permissions = $processor->processAccessPolicies($account, 'anything');
$this->assertEquals(new CalculatedPermissions($access_policy_permissions), $calculated_permissions);
}
/**
* Tests that everything works if no access policies are present.
*/
public function testNoCalculators() : void {
$account = $this->prophesize(AccountInterface::class)
->reveal();
$processor = $this->setUpAccessPolicyProcessor();
$no_permissions = new RefinableCalculatedPermissions();
$no_permissions->addCacheTags([
'access_policies',
]);
$calculated_permissions = $processor->processAccessPolicies($account, 'anything');
$this->assertEquals(new CalculatedPermissions($no_permissions), $calculated_permissions);
}
/**
* Tests the wrong scope exception.
*/
public function testWrongScopeException() : void {
$processor = $this->setUpAccessPolicyProcessor();
$processor->addAccessPolicy(new AlwaysAddsAccessPolicy());
$this->expectException(AccessPolicyScopeException::class);
$this->expectExceptionMessage(sprintf('The access policy "%s" returned permissions for scopes other than "%s".', AlwaysAddsAccessPolicy::class, 'bar'));
$processor->processAccessPolicies($this->prophesize(AccountInterface::class)
->reveal(), 'bar');
}
/**
* Tests the multiple scopes exception.
*/
public function testMultipleScopeException() : void {
$processor = $this->setUpAccessPolicyProcessor();
$processor->addAccessPolicy(new FooAccessPolicy());
$processor->addAccessPolicy(new AlwaysAddsAccessPolicy());
$this->expectException(AccessPolicyScopeException::class);
$this->expectExceptionMessage(sprintf('The access policy "%s" returned permissions for scopes other than "%s".', AlwaysAddsAccessPolicy::class, 'foo'));
$processor->processAccessPolicies($this->prophesize(AccountInterface::class)
->reveal(), 'foo');
}
/**
* Tests the multiple scopes exception.
*/
public function testMultipleScopeAlterException() : void {
$processor = $this->setUpAccessPolicyProcessor();
$processor->addAccessPolicy(new FooAccessPolicy());
$processor->addAccessPolicy(new AlwaysAltersAccessPolicy());
$this->expectException(AccessPolicyScopeException::class);
$this->expectExceptionMessage(sprintf('The access policy "%s" altered permissions in a scope other than "%s".', AlwaysAltersAccessPolicy::class, 'foo'));
$processor->processAccessPolicies($this->prophesize(AccountInterface::class)
->reveal(), 'foo');
}
/**
* Tests if the account switcher switches properly when user cache context is present.
*
* @param bool $has_user_context
* Whether a user based cache context is present.
* @param bool $is_current_user
* Whether the passed in account is the current user.
* @param bool $should_call_switcher
* Whether the account switcher should be called.
*
* @dataProvider accountSwitcherProvider
*/
public function testAccountSwitcher(bool $has_user_context, bool $is_current_user, bool $should_call_switcher) : void {
$account = $this->prophesize(AccountInterface::class);
$account->id()
->willReturn(2);
$account = $account->reveal();
$current_user = $this->prophesize(AccountProxyInterface::class);
$current_user->id()
->willReturn($is_current_user ? 2 : 13);
$account_switcher = $this->prophesize(AccountSwitcherInterface::class);
if ($should_call_switcher) {
$account_switcher->switchTo($account)
->shouldBeCalledTimes(1);
$account_switcher->switchBack()
->shouldBeCalledTimes(1);
}
else {
$account_switcher->switchTo($account)
->shouldNotBeCalled();
$account_switcher->switchBack()
->shouldNotBeCalled();
}
$processor = $this->setUpAccessPolicyProcessor(NULL, NULL, NULL, $current_user->reveal(), $account_switcher->reveal());
$processor->addAccessPolicy(new BarAccessPolicy());
if ($has_user_context) {
$processor->addAccessPolicy(new UserContextAccessPolicy());
}
$processor->processAccessPolicies($account, 'bar');
}
/**
* Data provider for testAccountSwitcher().
*
* @return array
* A list of testAccountSwitcher method arguments.
*/
public static function accountSwitcherProvider() {
$cases['no-user-context-no-current-user'] = [
'has_user_context' => FALSE,
'is_current_user' => FALSE,
'should_call_switcher' => FALSE,
];
$cases['no-user-context-current-user'] = [
'has_user_context' => FALSE,
'is_current_user' => TRUE,
'should_call_switcher' => FALSE,
];
$cases['user-context-no-current-user'] = [
'has_user_context' => TRUE,
'is_current_user' => FALSE,
'should_call_switcher' => TRUE,
];
$cases['user-context-current-user'] = [
'has_user_context' => TRUE,
'is_current_user' => TRUE,
'should_call_switcher' => FALSE,
];
return $cases;
}
/**
* Tests if the caches are called correctly.
*
* @dataProvider cachingProvider
*/
public function testCaching(bool $db_cache_hit, bool $static_cache_hit) : void {
if ($static_cache_hit) {
$this->assertFalse($db_cache_hit, 'DB cache should never be checked when there is a static hit.');
}
$account = $this->prophesize(AccountInterface::class)
->reveal();
$scope = 'bar';
$bar_access_policy = new BarAccessPolicy();
$bar_permissions = $bar_access_policy->calculatePermissions($account, $scope);
$bar_permissions->addCacheTags([
'access_policies',
]);
$none_refinable_bar_permissions = new CalculatedPermissions($bar_permissions);
$cache_static = $this->prophesize(VariationCacheInterface::class);
$cache_db = $this->prophesize(VariationCacheInterface::class);
if (!$static_cache_hit) {
if (!$db_cache_hit) {
$cache_db->get(Argument::cetera())
->willReturn(FALSE);
$cache_db->set(Argument::any(), $bar_permissions, Argument::cetera())
->shouldBeCalled();
}
else {
$cache_item = new CacheItem($bar_permissions);
$cache_db->get(Argument::cetera())
->willReturn($cache_item);
$cache_db->set()
->shouldNotBeCalled();
}
$cache_static->get(Argument::cetera())
->willReturn(FALSE);
$cache_static->set(Argument::any(), $none_refinable_bar_permissions, Argument::cetera())
->shouldBeCalled();
}
else {
$cache_item = new CacheItem($none_refinable_bar_permissions);
$cache_static->get(Argument::cetera())
->willReturn($cache_item);
$cache_static->set()
->shouldNotBeCalled();
}
$cache_static = $cache_static->reveal();
$cache_db = $cache_db->reveal();
$processor = $this->setUpAccessPolicyProcessor($cache_db, $cache_static);
$processor->addAccessPolicy($bar_access_policy);
$permissions = $processor->processAccessPolicies($account, $scope);
$this->assertEquals($none_refinable_bar_permissions, $permissions, 'Cached permission matches calculated.');
}
/**
* Data provider for testCaching().
*
* @return array
* A list of testAccountSwitcher method arguments.
*/
public static function cachingProvider() {
$cases = [
'no-cache' => [
FALSE,
FALSE,
],
'static-cache-hit' => [
FALSE,
TRUE,
],
'db-cache-hit' => [
TRUE,
FALSE,
],
];
return $cases;
}
/**
* Tests that only the cache contexts for policies that apply are added.
*/
public function testCacheContexts() : void {
// BazAccessPolicy and BarAlterAccessPolicy shouldn't add any contexts.
$initial_cacheability = (new CacheableMetadata())->addCacheContexts([
'foo',
'bar',
]);
$final_cacheability = (new CacheableMetadata())->addCacheContexts([
'foo',
'bar',
])
->addCacheTags([
'access_policies',
]);
$variation_cache = $this->prophesize(VariationCacheInterface::class);
$variation_cache->get(Argument::cetera())
->willReturn(FALSE);
$variation_cache->set([
'access_policies',
'anything',
], Argument::any(), $final_cacheability, $initial_cacheability)
->shouldBeCalled();
$cache_static = $this->prophesize(CacheBackendInterface::class);
$cache_static->get('access_policies:access_policy_processor:contexts:anything')
->willReturn(FALSE);
$cache_static->set('access_policies:access_policy_processor:contexts:anything', [
'foo',
'bar',
])
->shouldBeCalled();
$processor = $this->setUpAccessPolicyProcessor($variation_cache->reveal(), NULL, $cache_static->reveal());
foreach ([
new FooAccessPolicy(),
new BarAccessPolicy(),
new BazAccessPolicy(),
new BarAlterAccessPolicy(),
] as $access_policy) {
$processor->addAccessPolicy($access_policy);
}
$processor->processAccessPolicies($this->prophesize(AccountInterface::class)
->reveal(), 'anything');
}
/**
* Tests that the persistent cache contexts are added properly.
*/
public function testCacheContextCaching() : void {
$cache_entry = new \stdClass();
$cache_entry->data = [
'baz',
];
$cache_static = $this->prophesize(CacheBackendInterface::class);
$cache_static->get('access_policies:access_policy_processor:contexts:anything')
->willReturn($cache_entry);
$cache_static->set('access_policies:access_policy_processor:contexts:anything', Argument::any())
->shouldNotBeCalled();
// Hard-coded to "baz" because of the above cache entry.
$initial_cacheability = (new CacheableMetadata())->addCacheContexts([
'baz',
]);
// Still adds in "foo" and "bar" in calculatePermissions(). Under normal
// circumstances this would trigger an exception in VariationCache, but we
// deliberately poison the cache in this test to see if it's called.
$final_cacheability = (new CacheableMetadata())->addCacheContexts([
'foo',
'bar',
])
->addCacheTags([
'access_policies',
]);
$variation_cache = $this->prophesize(VariationCacheInterface::class);
$variation_cache->get([
'access_policies',
'anything',
], $initial_cacheability)
->shouldBeCalled()
->willReturn(FALSE);
$variation_cache->set([
'access_policies',
'anything',
], Argument::any(), $final_cacheability, $initial_cacheability)
->shouldBeCalled();
$processor = $this->setUpAccessPolicyProcessor($variation_cache->reveal(), NULL, $cache_static->reveal());
foreach ([
new FooAccessPolicy(),
new BarAccessPolicy(),
new BazAccessPolicy(),
new BarAlterAccessPolicy(),
] as $access_policy) {
$processor->addAccessPolicy($access_policy);
}
$processor->processAccessPolicies($this->prophesize(AccountInterface::class)
->reveal(), 'anything');
}
/**
* Sets up the access policy processor.
*
* @return \Drupal\Core\Session\AccessPolicyProcessorInterface
*/
protected function setUpAccessPolicyProcessor(?VariationCacheInterface $variation_cache = NULL, ?VariationCacheInterface $variation_cache_static = NULL, ?CacheBackendInterface $cache_static = NULL, ?AccountProxyInterface $current_user = NULL, ?AccountSwitcherInterface $account_switcher = NULL) {
// Prophecy does not accept a willReturn call on a mocked method if said
// method has a return type of void. However, without willReturn() or any
// other will* call, the method mock will not be registered.
$prophecy_workaround = function () {
};
if (!isset($variation_cache)) {
$variation_cache = $this->prophesize(VariationCacheInterface::class);
$variation_cache->get(Argument::cetera())
->willReturn(FALSE);
$variation_cache->set(Argument::cetera())
->will($prophecy_workaround);
$variation_cache = $variation_cache->reveal();
}
if (!isset($variation_cache_static)) {
$variation_cache_static = $this->prophesize(VariationCacheInterface::class);
$variation_cache_static->get(Argument::cetera())
->willReturn(FALSE);
$variation_cache_static->set(Argument::cetera())
->will($prophecy_workaround);
$variation_cache_static = $variation_cache_static->reveal();
}
if (!isset($cache_static)) {
$cache_static = $this->prophesize(CacheBackendInterface::class);
$cache_static->get(Argument::cetera())
->willReturn(FALSE);
$cache_static->set(Argument::cetera())
->will($prophecy_workaround);
$cache_static = $cache_static->reveal();
}
if (!isset($current_user)) {
$current_user = $this->prophesize(AccountProxyInterface::class)
->reveal();
}
if (!isset($account_switcher)) {
$account_switcher = $this->prophesize(AccountSwitcherInterface::class)
->reveal();
}
return new AccessPolicyProcessor($variation_cache, $variation_cache_static, $cache_static, $current_user, $account_switcher);
}
}
Members
Title Sort descending | Deprecated | Modifiers | Object type | Summary | Overriden Title | Overrides |
---|---|---|---|---|---|---|
AccessPolicyProcessorTest::accountSwitcherProvider | public static | function | Data provider for testAccountSwitcher(). | |||
AccessPolicyProcessorTest::cachingProvider | public static | function | Data provider for testCaching(). | |||
AccessPolicyProcessorTest::setUp | public | function | Overrides UnitTestCase::setUp | |||
AccessPolicyProcessorTest::setUpAccessPolicyProcessor | protected | function | Sets up the access policy processor. | |||
AccessPolicyProcessorTest::testAccountSwitcher | public | function | Tests if the account switcher switches properly when user cache context is present. | |||
AccessPolicyProcessorTest::testAlterPermissions | public | function | Tests that access policies can alter the final result. | |||
AccessPolicyProcessorTest::testAlterPermissionsNoApply | public | function | Tests that alters that do not apply are not processed. | |||
AccessPolicyProcessorTest::testCacheContextCaching | public | function | Tests that the persistent cache contexts are added properly. | |||
AccessPolicyProcessorTest::testCacheContexts | public | function | Tests that only the cache contexts for policies that apply are added. | |||
AccessPolicyProcessorTest::testCaching | public | function | Tests if the caches are called correctly. | |||
AccessPolicyProcessorTest::testCalculatePermissions | public | function | Tests that access policies are properly processed. | |||
AccessPolicyProcessorTest::testCalculatePermissionsNoApply | public | function | Tests that access policies that do not apply are not processed. | |||
AccessPolicyProcessorTest::testEmptyCalculator | public | function | Tests that access policies which do nothing are properly processed. | |||
AccessPolicyProcessorTest::testMultipleScopeAlterException | public | function | Tests the multiple scopes exception. | |||
AccessPolicyProcessorTest::testMultipleScopeException | public | function | Tests the multiple scopes exception. | |||
AccessPolicyProcessorTest::testNoCalculators | public | function | Tests that everything works if no access policies are present. | |||
AccessPolicyProcessorTest::testWrongScopeException | public | function | Tests the wrong scope exception. | |||
PhpUnitWarnings::$deprecationWarnings | private static | property | Deprecation warnings from PHPUnit to raise with @trigger_error(). | |||
PhpUnitWarnings::addWarning | public | function | Converts PHPUnit deprecation warnings to E_USER_DEPRECATED. | |||
RandomGeneratorTrait::getRandomGenerator | protected | function | Gets the random generator for the utility methods. | |||
RandomGeneratorTrait::randomMachineName | protected | function | Generates a unique random string containing letters and numbers. | |||
RandomGeneratorTrait::randomObject | public | function | Generates a random PHP object. | |||
RandomGeneratorTrait::randomString | public | function | Generates a pseudo-random string of ASCII characters of codes 32 to 126. | |||
RandomGeneratorTrait::randomStringValidate | Deprecated | public | function | Callback for random string validation. | ||
UnitTestCase::$root | protected | property | The app root. | 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::getStringTranslationStub | public | function | Returns a stub translation manager that just returns the passed string. | |||
UnitTestCase::setUpBeforeClass | public static | function | ||||
UnitTestCase::__get | public | function |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.