Update to Drupal 8.0.0-beta15. For more information, see: https://www.drupal.org/node/2563023
This commit is contained in:
parent
2720a9ec4b
commit
f3791f1da3
1898 changed files with 54300 additions and 11481 deletions
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,621 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\DependencyInjection\Dumper\OptimizedPhpArrayDumperTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\DependencyInjection\Dumper {
|
||||
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\Parameter;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\DependencyInjection\Dumper\OptimizedPhpArrayDumper
|
||||
* @group DependencyInjection
|
||||
*/
|
||||
class OptimizedPhpArrayDumperTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* The container builder instance.
|
||||
*
|
||||
* @var \Symfony\Component\DependencyInjection\ContainerBuilder
|
||||
*/
|
||||
protected $containerBuilder;
|
||||
|
||||
/**
|
||||
* The definition for the container to build in tests.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $containerDefinition;
|
||||
|
||||
/**
|
||||
* Whether the dumper uses the machine-optimized format or not.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $machineFormat = TRUE;
|
||||
|
||||
/**
|
||||
* Stores the dumper class to use.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $dumperClass = '\Drupal\Component\DependencyInjection\Dumper\OptimizedPhpArrayDumper';
|
||||
|
||||
/**
|
||||
* The dumper instance.
|
||||
*
|
||||
* @var \Symfony\Component\DependencyInjection\Dumper\DumperInterface
|
||||
*/
|
||||
protected $dumper;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
// Setup a mock container builder.
|
||||
$this->containerBuilder = $this->prophesize('\Symfony\Component\DependencyInjection\ContainerBuilder');
|
||||
$this->containerBuilder->getAliases()->willReturn(array());
|
||||
$this->containerBuilder->getParameterBag()->willReturn(new ParameterBag());
|
||||
$this->containerBuilder->getDefinitions()->willReturn(NULL);
|
||||
$this->containerBuilder->isFrozen()->willReturn(TRUE);
|
||||
|
||||
$definition = array();
|
||||
$definition['aliases'] = array();
|
||||
$definition['parameters'] = array();
|
||||
$definition['services'] = array();
|
||||
$definition['frozen'] = TRUE;
|
||||
$definition['machine_format'] = $this->machineFormat;
|
||||
|
||||
$this->containerDefinition = $definition;
|
||||
|
||||
// Create the dumper.
|
||||
$this->dumper = new $this->dumperClass($this->containerBuilder->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that an empty container works properly.
|
||||
*
|
||||
* @covers ::dump
|
||||
* @covers ::getArray
|
||||
* @covers ::supportsMachineFormat
|
||||
*/
|
||||
public function testDumpForEmptyContainer() {
|
||||
$serialized_definition = $this->dumper->dump();
|
||||
$this->assertEquals(serialize($this->containerDefinition), $serialized_definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that alias processing works properly.
|
||||
*
|
||||
* @covers ::getAliases
|
||||
*
|
||||
* @dataProvider getAliasesDataProvider
|
||||
*/
|
||||
public function testGetAliases($aliases, $definition_aliases) {
|
||||
$this->containerDefinition['aliases'] = $definition_aliases;
|
||||
$this->containerBuilder->getAliases()->willReturn($aliases);
|
||||
$this->assertEquals($this->containerDefinition, $this->dumper->getArray(), 'Expected definition matches dump.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetAliases().
|
||||
*
|
||||
* @return array[]
|
||||
* Returns data-set elements with:
|
||||
* - aliases as returned by ContainerBuilder.
|
||||
* - aliases as expected in the container definition.
|
||||
*/
|
||||
public function getAliasesDataProvider() {
|
||||
return array(
|
||||
array(array(), array()),
|
||||
array(
|
||||
array('foo' => 'foo.alias'),
|
||||
array('foo' => 'foo.alias'),
|
||||
),
|
||||
array(
|
||||
array('foo' => 'foo.alias', 'foo.alias' => 'foo.alias.alias'),
|
||||
array('foo' => 'foo.alias.alias', 'foo.alias' => 'foo.alias.alias'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that parameter processing works properly.
|
||||
*
|
||||
* @covers ::getParameters
|
||||
* @covers ::prepareParameters
|
||||
* @covers ::escape
|
||||
* @covers ::dumpValue
|
||||
* @covers ::getReferenceCall
|
||||
*
|
||||
* @dataProvider getParametersDataProvider
|
||||
*/
|
||||
public function testGetParameters($parameters, $definition_parameters, $is_frozen) {
|
||||
$this->containerDefinition['parameters'] = $definition_parameters;
|
||||
$this->containerDefinition['frozen'] = $is_frozen;
|
||||
|
||||
$parameter_bag = new ParameterBag($parameters);
|
||||
$this->containerBuilder->getParameterBag()->willReturn($parameter_bag);
|
||||
$this->containerBuilder->isFrozen()->willReturn($is_frozen);
|
||||
|
||||
if (isset($parameters['reference'])) {
|
||||
$definition = new Definition('\stdClass');
|
||||
$this->containerBuilder->getDefinition('referenced_service')->willReturn($definition);
|
||||
}
|
||||
|
||||
$this->assertEquals($this->containerDefinition, $this->dumper->getArray(), 'Expected definition matches dump.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetParameters().
|
||||
*
|
||||
* @return array[]
|
||||
* Returns data-set elements with:
|
||||
* - parameters as returned by ContainerBuilder.
|
||||
* - parameters as expected in the container definition.
|
||||
* - frozen value
|
||||
*/
|
||||
public function getParametersDataProvider() {
|
||||
return array(
|
||||
array(array(), array(), TRUE),
|
||||
array(
|
||||
array('foo' => 'value_foo'),
|
||||
array('foo' => 'value_foo'),
|
||||
TRUE,
|
||||
),
|
||||
array(
|
||||
array('foo' => array('llama' => 'yes')),
|
||||
array('foo' => array('llama' => 'yes')),
|
||||
TRUE,
|
||||
),
|
||||
array(
|
||||
array('foo' => '%llama%', 'llama' => 'yes'),
|
||||
array('foo' => '%%llama%%', 'llama' => 'yes'),
|
||||
TRUE,
|
||||
),
|
||||
array(
|
||||
array('foo' => '%llama%', 'llama' => 'yes'),
|
||||
array('foo' => '%llama%', 'llama' => 'yes'),
|
||||
FALSE,
|
||||
),
|
||||
array(
|
||||
array('reference' => new Reference('referenced_service')),
|
||||
array('reference' => $this->getServiceCall('referenced_service')),
|
||||
TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that service processing works properly.
|
||||
*
|
||||
* @covers ::getServiceDefinitions
|
||||
* @covers ::getServiceDefinition
|
||||
* @covers ::dumpMethodCalls
|
||||
* @covers ::dumpCollection
|
||||
* @covers ::dumpCallable
|
||||
* @covers ::dumpValue
|
||||
* @covers ::getPrivateServiceCall
|
||||
* @covers ::getReferenceCall
|
||||
* @covers ::getServiceCall
|
||||
* @covers ::getParameterCall
|
||||
*
|
||||
* @dataProvider getDefinitionsDataProvider
|
||||
*/
|
||||
public function testGetServiceDefinitions($services, $definition_services) {
|
||||
$this->containerDefinition['services'] = $definition_services;
|
||||
|
||||
$this->containerBuilder->getDefinitions()->willReturn($services);
|
||||
|
||||
$bar_definition = new Definition('\stdClass');
|
||||
$this->containerBuilder->getDefinition('bar')->willReturn($bar_definition);
|
||||
|
||||
$private_definition = new Definition('\stdClass');
|
||||
$private_definition->setPublic(FALSE);
|
||||
|
||||
$this->containerBuilder->getDefinition('private_definition')->willReturn($private_definition);
|
||||
|
||||
$this->assertEquals($this->containerDefinition, $this->dumper->getArray(), 'Expected definition matches dump.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetServiceDefinitions().
|
||||
*
|
||||
* @return array[]
|
||||
* Returns data-set elements with:
|
||||
* - parameters as returned by ContainerBuilder.
|
||||
* - parameters as expected in the container definition.
|
||||
* - frozen value
|
||||
*/
|
||||
public function getDefinitionsDataProvider() {
|
||||
$base_service_definition = array(
|
||||
'class' => '\stdClass',
|
||||
'public' => TRUE,
|
||||
'file' => FALSE,
|
||||
'synthetic' => FALSE,
|
||||
'lazy' => FALSE,
|
||||
'arguments' => array(),
|
||||
'arguments_count' => 0,
|
||||
'properties' => array(),
|
||||
'calls' => array(),
|
||||
'scope' => ContainerInterface::SCOPE_CONTAINER,
|
||||
'shared' => TRUE,
|
||||
'factory' => FALSE,
|
||||
'configurator' => FALSE,
|
||||
);
|
||||
|
||||
// Test basic flags.
|
||||
$service_definitions[] = array() + $base_service_definition;
|
||||
|
||||
$service_definitions[] = array(
|
||||
'public' => FALSE,
|
||||
) + $base_service_definition;
|
||||
|
||||
$service_definitions[] = array(
|
||||
'file' => 'test_include.php',
|
||||
) + $base_service_definition;
|
||||
|
||||
$service_definitions[] = array(
|
||||
'synthetic' => TRUE,
|
||||
) + $base_service_definition;
|
||||
|
||||
$service_definitions[] = array(
|
||||
'lazy' => TRUE,
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test a basic public Reference.
|
||||
$service_definitions[] = array(
|
||||
'arguments' => array('foo', new Reference('bar')),
|
||||
'arguments_count' => 2,
|
||||
'arguments_expected' => $this->getCollection(array('foo', $this->getServiceCall('bar'))),
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test a public reference that should not throw an Exception.
|
||||
$reference = new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE);
|
||||
$service_definitions[] = array(
|
||||
'arguments' => array($reference),
|
||||
'arguments_count' => 1,
|
||||
'arguments_expected' => $this->getCollection(array($this->getServiceCall('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE))),
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test a private shared service, denoted by having a Reference.
|
||||
$private_definition = array(
|
||||
'class' => '\stdClass',
|
||||
'public' => FALSE,
|
||||
'arguments_count' => 0,
|
||||
);
|
||||
|
||||
$service_definitions[] = array(
|
||||
'arguments' => array('foo', new Reference('private_definition')),
|
||||
'arguments_count' => 2,
|
||||
'arguments_expected' => $this->getCollection(array(
|
||||
'foo',
|
||||
$this->getPrivateServiceCall('private_definition', $private_definition, TRUE),
|
||||
)),
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test a private non-shared service, denoted by having a Definition.
|
||||
$private_definition_object = new Definition('\stdClass');
|
||||
$private_definition_object->setPublic(FALSE);
|
||||
|
||||
$service_definitions[] = array(
|
||||
'arguments' => array('foo', $private_definition_object),
|
||||
'arguments_count' => 2,
|
||||
'arguments_expected' => $this->getCollection(array(
|
||||
'foo',
|
||||
$this->getPrivateServiceCall(NULL, $private_definition),
|
||||
)),
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test a deep collection without a reference.
|
||||
$service_definitions[] = array(
|
||||
'arguments' => array(array(array('foo'))),
|
||||
'arguments_count' => 1,
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test a deep collection with a reference to resolve.
|
||||
$service_definitions[] = array(
|
||||
'arguments' => array(array(new Reference('bar'))),
|
||||
'arguments_count' => 1,
|
||||
'arguments_expected' => $this->getCollection(array($this->getCollection(array($this->getServiceCall('bar'))))),
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test a collection with a variable to resolve.
|
||||
$service_definitions[] = array(
|
||||
'arguments' => array(new Parameter('llama_parameter')),
|
||||
'arguments_count' => 1,
|
||||
'arguments_expected' => $this->getCollection(array($this->getParameterCall('llama_parameter'))),
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test objects that have _serviceId property.
|
||||
$drupal_service = new \stdClass();
|
||||
$drupal_service->_serviceId = 'bar';
|
||||
|
||||
$service_definitions[] = array(
|
||||
'arguments' => array($drupal_service),
|
||||
'arguments_count' => 1,
|
||||
'arguments_expected' => $this->getCollection(array($this->getServiceCall('bar'))),
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test getMethodCalls.
|
||||
$calls = array(
|
||||
array('method', $this->getCollection(array())),
|
||||
array('method2', $this->getCollection(array())),
|
||||
);
|
||||
$service_definitions[] = array(
|
||||
'calls' => $calls,
|
||||
) + $base_service_definition;
|
||||
|
||||
$service_definitions[] = array(
|
||||
'scope' => ContainerInterface::SCOPE_PROTOTYPE,
|
||||
'shared' => FALSE,
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test factory.
|
||||
$service_definitions[] = array(
|
||||
'factory' => array(new Reference('bar'), 'factoryMethod'),
|
||||
'factory_expected' => array($this->getServiceCall('bar'), 'factoryMethod'),
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test invalid factory - needed to test deep dumpValue().
|
||||
$service_definitions[] = array(
|
||||
'factory' => array(array('foo', 'llama'), 'factoryMethod'),
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test properties.
|
||||
$service_definitions[] = array(
|
||||
'properties' => array('_value' => 'llama'),
|
||||
) + $base_service_definition;
|
||||
|
||||
// Test configurator.
|
||||
$service_definitions[] = array(
|
||||
'configurator' => array(new Reference('bar'), 'configureService'),
|
||||
'configurator_expected' => array($this->getServiceCall('bar'), 'configureService'),
|
||||
) + $base_service_definition;
|
||||
|
||||
$services_provided = array();
|
||||
$services_provided[] = array(
|
||||
array(),
|
||||
array(),
|
||||
);
|
||||
|
||||
foreach ($service_definitions as $service_definition) {
|
||||
$definition = $this->prophesize('\Symfony\Component\DependencyInjection\Definition');
|
||||
$definition->getClass()->willReturn($service_definition['class']);
|
||||
$definition->isPublic()->willReturn($service_definition['public']);
|
||||
$definition->getFile()->willReturn($service_definition['file']);
|
||||
$definition->isSynthetic()->willReturn($service_definition['synthetic']);
|
||||
$definition->isLazy()->willReturn($service_definition['lazy']);
|
||||
$definition->getArguments()->willReturn($service_definition['arguments']);
|
||||
$definition->getProperties()->willReturn($service_definition['properties']);
|
||||
$definition->getMethodCalls()->willReturn($service_definition['calls']);
|
||||
$definition->getScope()->willReturn($service_definition['scope']);
|
||||
$definition->getDecoratedService()->willReturn(NULL);
|
||||
$definition->getFactory()->willReturn($service_definition['factory']);
|
||||
$definition->getConfigurator()->willReturn($service_definition['configurator']);
|
||||
|
||||
// Preserve order.
|
||||
$filtered_service_definition = array();
|
||||
foreach ($base_service_definition as $key => $value) {
|
||||
$filtered_service_definition[$key] = $service_definition[$key];
|
||||
unset($service_definition[$key]);
|
||||
|
||||
if ($key == 'class' || $key == 'arguments_count') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($filtered_service_definition[$key] === $base_service_definition[$key]) {
|
||||
unset($filtered_service_definition[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add remaining properties.
|
||||
$filtered_service_definition += $service_definition;
|
||||
|
||||
// Allow to set _expected values.
|
||||
foreach (array('arguments', 'factory', 'configurator') as $key) {
|
||||
$expected = $key . '_expected';
|
||||
if (isset($filtered_service_definition[$expected])) {
|
||||
$filtered_service_definition[$key] = $filtered_service_definition[$expected];
|
||||
unset($filtered_service_definition[$expected]);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any remaining scope.
|
||||
unset($filtered_service_definition['scope']);
|
||||
|
||||
if (isset($filtered_service_definition['public']) && $filtered_service_definition['public'] === FALSE) {
|
||||
$services_provided[] = array(
|
||||
array('foo_service' => $definition->reveal()),
|
||||
array(),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
$services_provided[] = array(
|
||||
array('foo_service' => $definition->reveal()),
|
||||
array('foo_service' => $this->serializeDefinition($filtered_service_definition)),
|
||||
);
|
||||
}
|
||||
|
||||
return $services_provided;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to serialize a definition.
|
||||
*
|
||||
* Used to override serialization.
|
||||
*/
|
||||
protected function serializeDefinition(array $service_definition) {
|
||||
return serialize($service_definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return a service definition.
|
||||
*/
|
||||
protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) {
|
||||
return (object) array(
|
||||
'type' => 'service',
|
||||
'id' => $id,
|
||||
'invalidBehavior' => $invalid_behavior,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the correct InvalidArgumentException is thrown for getScope().
|
||||
*
|
||||
* @covers ::getServiceDefinition
|
||||
*
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function testGetServiceDefinitionWithInvalidScope() {
|
||||
$bar_definition = new Definition('\stdClass');
|
||||
$bar_definition->setScope('foo_scope');
|
||||
$services['bar'] = $bar_definition;
|
||||
|
||||
$this->containerBuilder->getDefinitions()->willReturn($services);
|
||||
$this->dumper->getArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that getDecoratedService() is unsupported.
|
||||
*
|
||||
* Tests that the correct InvalidArgumentException is thrown for
|
||||
* getDecoratedService().
|
||||
*
|
||||
* @covers ::getServiceDefinition
|
||||
*
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function testGetServiceDefinitionForDecoratedService() {
|
||||
$bar_definition = new Definition('\stdClass');
|
||||
$bar_definition->setDecoratedService(new Reference('foo'));
|
||||
$services['bar'] = $bar_definition;
|
||||
|
||||
$this->containerBuilder->getDefinitions()->willReturn($services);
|
||||
$this->dumper->getArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the correct RuntimeException is thrown for expressions.
|
||||
*
|
||||
* @covers ::dumpValue
|
||||
*
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||
*/
|
||||
public function testGetServiceDefinitionForExpression() {
|
||||
$expression = new Expression();
|
||||
|
||||
$bar_definition = new Definition('\stdClass');
|
||||
$bar_definition->addArgument($expression);
|
||||
$services['bar'] = $bar_definition;
|
||||
|
||||
$this->containerBuilder->getDefinitions()->willReturn($services);
|
||||
$this->dumper->getArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the correct RuntimeException is thrown for dumping an object.
|
||||
*
|
||||
* @covers ::dumpValue
|
||||
*
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||
*/
|
||||
public function testGetServiceDefinitionForObject() {
|
||||
$service = new \stdClass();
|
||||
|
||||
$bar_definition = new Definition('\stdClass');
|
||||
$bar_definition->addArgument($service);
|
||||
$services['bar'] = $bar_definition;
|
||||
|
||||
$this->containerBuilder->getDefinitions()->willReturn($services);
|
||||
$this->dumper->getArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the correct RuntimeException is thrown for dumping a resource.
|
||||
*
|
||||
* @covers ::dumpValue
|
||||
*
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||
*/
|
||||
public function testGetServiceDefinitionForResource() {
|
||||
$resource = fopen('php://memory', 'r');
|
||||
|
||||
$bar_definition = new Definition('\stdClass');
|
||||
$bar_definition->addArgument($resource);
|
||||
$services['bar'] = $bar_definition;
|
||||
|
||||
$this->containerBuilder->getDefinitions()->willReturn($services);
|
||||
$this->dumper->getArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return a private service definition.
|
||||
*/
|
||||
protected function getPrivateServiceCall($id, $service_definition, $shared = FALSE) {
|
||||
if (!$id) {
|
||||
$hash = sha1(serialize($service_definition));
|
||||
$id = 'private__' . $hash;
|
||||
}
|
||||
return (object) array(
|
||||
'type' => 'private_service',
|
||||
'id' => $id,
|
||||
'value' => $service_definition,
|
||||
'shared' => $shared,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return a machine-optimized collection.
|
||||
*/
|
||||
protected function getCollection($collection, $resolve = TRUE) {
|
||||
return (object) array(
|
||||
'type' => 'collection',
|
||||
'value' => $collection,
|
||||
'resolve' => $resolve,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return a parameter definition.
|
||||
*/
|
||||
protected function getParameterCall($name) {
|
||||
return (object) array(
|
||||
'type' => 'parameter',
|
||||
'name' => $name,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* As Drupal Core does not ship with ExpressionLanguage component we need to
|
||||
* define a dummy, else it cannot be tested.
|
||||
*/
|
||||
namespace Symfony\Component\ExpressionLanguage {
|
||||
if (!class_exists('\Symfony\Component\ExpressionLanguage\Expression')) {
|
||||
/**
|
||||
* Dummy class to ensure non-existent Symfony component can be tested.
|
||||
*/
|
||||
class Expression {
|
||||
|
||||
/**
|
||||
* Gets the string representation of the expression.
|
||||
*/
|
||||
public function __toString() {
|
||||
return 'dummy_expression';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\DependencyInjection\Dumper\PhpArrayDumperTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\DependencyInjection\Dumper;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\DependencyInjection\Dumper\PhpArrayDumper
|
||||
* @group DependencyInjection
|
||||
*/
|
||||
class PhpArrayDumperTest extends OptimizedPhpArrayDumperTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
$this->machineFormat = FALSE;
|
||||
$this->dumperClass = '\Drupal\Component\DependencyInjection\Dumper\PhpArrayDumper';
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function serializeDefinition(array $service_definition) {
|
||||
return $service_definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) {
|
||||
if ($invalid_behavior !== ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) {
|
||||
return sprintf('@?%s', $id);
|
||||
}
|
||||
|
||||
return sprintf('@%s', $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getParameterCall($name) {
|
||||
return '%' . $name . '%';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getCollection($collection, $resolve = TRUE) {
|
||||
return $collection;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains a test function for container 'file' include testing.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test function for container testing.
|
||||
*
|
||||
* @return string
|
||||
* A string just for testing.
|
||||
*/
|
||||
function container_test_file_service_test_service_function() {
|
||||
return 'Hello Container';
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\DependencyInjection\PhpArrayContainerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\DependencyInjection\PhpArrayContainer
|
||||
* @group DependencyInjection
|
||||
*/
|
||||
class PhpArrayContainerTest extends ContainerTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
$this->machineFormat = FALSE;
|
||||
$this->containerClass = '\Drupal\Component\DependencyInjection\PhpArrayContainer';
|
||||
$this->containerDefinition = $this->getMockContainerDefinition();
|
||||
$this->container = new $this->containerClass($this->containerDefinition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return a service definition.
|
||||
*/
|
||||
protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) {
|
||||
if ($invalid_behavior !== ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) {
|
||||
return sprintf('@?%s', $id);
|
||||
}
|
||||
|
||||
return sprintf('@%s', $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return a service definition.
|
||||
*/
|
||||
protected function getParameterCall($name) {
|
||||
return '%' . $name . '%';
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return a machine-optimized '@notation'.
|
||||
*/
|
||||
protected function getCollection($collection, $resolve = TRUE) {
|
||||
return $collection;
|
||||
}
|
||||
|
||||
}
|
|
@ -68,15 +68,12 @@ class DrupalComponentTest extends UnitTestCase {
|
|||
*/
|
||||
protected function assertNoCoreUsage($class_path) {
|
||||
$contents = file_get_contents($class_path);
|
||||
if (preg_match_all('/^.*Drupal\\\Core.*$/m', $contents, $matches)) {
|
||||
foreach ($matches[0] as $line) {
|
||||
if ((strpos($line, '@see ') === FALSE)) {
|
||||
$this->fail(
|
||||
"Illegal reference to 'Drupal\\Core' namespace in $class_path"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
preg_match_all('/^.*Drupal\\\Core.*$/m', $contents, $matches);
|
||||
$matches = array_filter($matches[0], function($line) {
|
||||
// Filter references to @see as they don't really matter.
|
||||
return strpos($line, '@see') === FALSE;
|
||||
});
|
||||
$this->assertEmpty($matches, "Checking for illegal reference to 'Drupal\\Core' namespace in $class_path");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -75,6 +75,7 @@ class FileStorageReadOnlyTest extends PhpStorageTestBase {
|
|||
// Saving and deleting should always fail.
|
||||
$this->assertFalse($php_read->save($name, $code));
|
||||
$this->assertFalse($php_read->delete($name));
|
||||
unset($GLOBALS[$random]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -86,6 +86,7 @@ class FileStorageTest extends PhpStorageTestBase {
|
|||
|
||||
// Should still return TRUE if directory has already been deleted.
|
||||
$this->assertTrue($php->deleteAll(), 'Delete all succeeds with nothing to delete');
|
||||
unset($GLOBALS[$random]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -124,6 +124,7 @@ abstract class MTimeProtectedFileStorageBase extends PhpStorageTestBase {
|
|||
$this->assertSame($php->load($name), $this->expected[$i]);
|
||||
$this->assertSame($GLOBALS['hacked'], $this->expected[$i]);
|
||||
}
|
||||
unset($GLOBALS['hacked']);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\Tests\Component\PhpStorage;
|
||||
|
||||
use Drupal\Component\PhpStorage\PhpStorageInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
|
||||
|
@ -49,6 +50,9 @@ abstract class PhpStorageTestBase extends UnitTestCase {
|
|||
$php->load($name);
|
||||
$this->assertTrue($GLOBALS[$random], 'File saved correctly with correct value');
|
||||
|
||||
// Run additional asserts.
|
||||
$this->additionalAssertCRUD($php, $name);
|
||||
|
||||
// If the file was successfully loaded, it must also exist, but ensure the
|
||||
// exists() method returns that correctly.
|
||||
$this->assertTrue($php->exists($name), 'Exists works correctly');
|
||||
|
@ -60,6 +64,20 @@ abstract class PhpStorageTestBase extends UnitTestCase {
|
|||
// Ensure delete() can be called on a non-existing file. It should return
|
||||
// FALSE, but not trigger errors.
|
||||
$this->assertFalse($php->delete($name), 'Delete fails on missing file');
|
||||
unset($GLOBALS[$random]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional asserts to be run.
|
||||
*
|
||||
* @param \Drupal\Component\PhpStorage\PhpStorageInterface $php
|
||||
* The PHP storage object.
|
||||
* @param string $name
|
||||
* The name of an object. It should exist in the storage.
|
||||
*/
|
||||
protected function additionalAssertCRUD(PhpStorageInterface $php, $name) {
|
||||
// By default do not do any additional asserts. This is a way of extending
|
||||
// tests in contrib.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -259,4 +259,55 @@ class HtmlTest extends UnitTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Html::escape().
|
||||
*
|
||||
* @dataProvider providerEscape
|
||||
* @covers ::escape
|
||||
*/
|
||||
public function testEscape($expected, $text) {
|
||||
$this->assertEquals($expected, Html::escape($text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testEscape().
|
||||
*
|
||||
* @see testCheckPlain()
|
||||
*/
|
||||
public function providerEscape() {
|
||||
return array(
|
||||
array('Drupal', 'Drupal'),
|
||||
array('<script>', '<script>'),
|
||||
array('&lt;script&gt;', '<script>'),
|
||||
array('&#34;', '"'),
|
||||
array('"', '"'),
|
||||
array('&quot;', '"'),
|
||||
array(''', "'"),
|
||||
array('&#039;', '''),
|
||||
array('©', '©'),
|
||||
array('→', '→'),
|
||||
array('➼', '➼'),
|
||||
array('€', '€'),
|
||||
array('Drup<75>al', "Drup\x80al"),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests relationship between escaping and decoding HTML entities.
|
||||
*
|
||||
* @covers ::decodeEntities
|
||||
* @covers ::escape
|
||||
*/
|
||||
public function testDecodeEntitiesAndEscape() {
|
||||
$string = "<em>répété</em>";
|
||||
$escaped = Html::escape($string);
|
||||
$this->assertSame('<em>répét&eacute;</em>', $escaped);
|
||||
$decoded = Html::decodeEntities($escaped);
|
||||
$this->assertSame('<em>répété</em>', $decoded);
|
||||
$decoded = Html::decodeEntities($decoded);
|
||||
$this->assertSame('<em>répété</em>', $decoded);
|
||||
$escaped = Html::escape($decoded);
|
||||
$this->assertSame('<em>répété</em>', $escaped);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\Random;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
|
@ -39,7 +38,7 @@ class RandomTest extends UnitTestCase {
|
|||
$random = new Random();
|
||||
for ($i = 0; $i <= 50; $i++) {
|
||||
$str = $random->string(1, TRUE);
|
||||
$this->assertFalse(isset($strings[$str]), SafeMarkup::format('Generated duplicate random string !string', array('!string' => $str)));
|
||||
$this->assertFalse(isset($strings[$str]), 'Generated duplicate random string ' . $str);
|
||||
$strings[$str] = TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +53,7 @@ class RandomTest extends UnitTestCase {
|
|||
$random = new Random();
|
||||
for ($i = 0; $i <= 10; $i++) {
|
||||
$str = $random->name(1, TRUE);
|
||||
$this->assertFalse(isset($names[$str]), SafeMarkup::format('Generated duplicate random name !name', array('!name' => $str)));
|
||||
$this->assertFalse(isset($names[$str]), 'Generated duplicate random name ' . $str);
|
||||
$names[$str] = TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Utility\Xss;
|
||||
use Drupal\Component\Utility\SafeStringInterface;
|
||||
use Drupal\Component\Utility\SafeStringTrait;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
|
@ -20,54 +21,81 @@ use Drupal\Tests\UnitTestCase;
|
|||
class SafeMarkupTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests SafeMarkup::set() and SafeMarkup::isSafe().
|
||||
* Helper function to add a string to the safe list for testing.
|
||||
*
|
||||
* @dataProvider providerSet
|
||||
* @param string $string
|
||||
* The content to be marked as secure.
|
||||
* @param string $strategy
|
||||
* The escaping strategy used for this string. Two values are supported
|
||||
* by default:
|
||||
* - 'html': (default) The string is safe for use in HTML code.
|
||||
* - 'all': The string is safe for all use cases.
|
||||
* See the
|
||||
* @link http://twig.sensiolabs.org/doc/filters/escape.html Twig escape documentation @endlink
|
||||
* for more information on escaping strategies in Twig.
|
||||
*
|
||||
* @param string $text
|
||||
* The text or object to provide to SafeMarkup::set().
|
||||
* @param string $message
|
||||
* The message to provide as output for the test.
|
||||
*
|
||||
* @covers ::set
|
||||
* @return string
|
||||
* The input string that was marked as safe.
|
||||
*/
|
||||
public function testSet($text, $message) {
|
||||
$returned = SafeMarkup::set($text);
|
||||
$this->assertTrue(is_string($returned), 'The return value of SafeMarkup::set() is really a string');
|
||||
$this->assertEquals($returned, $text, 'The passed in value should be equal to the string value according to PHP');
|
||||
$this->assertTrue(SafeMarkup::isSafe($text), $message);
|
||||
$this->assertTrue(SafeMarkup::isSafe($returned), 'The return value has been marked as safe');
|
||||
protected function safeMarkupSet($string, $strategy = 'html') {
|
||||
$reflected_class = new \ReflectionClass('\Drupal\Component\Utility\SafeMarkup');
|
||||
$reflected_property = $reflected_class->getProperty('safeStrings');
|
||||
$reflected_property->setAccessible(true);
|
||||
$current_value = $reflected_property->getValue();
|
||||
$current_value[$string][$strategy] = TRUE;
|
||||
$reflected_property->setValue($current_value);
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SafeMarkup::isSafe() with different providers.
|
||||
*
|
||||
* @covers ::isSafe
|
||||
*/
|
||||
public function testStrategy() {
|
||||
$returned = $this->safeMarkupSet('string0', 'html');
|
||||
$this->assertTrue(SafeMarkup::isSafe($returned), 'String set with "html" provider is safe for default (html)');
|
||||
$returned = $this->safeMarkupSet('string1', 'all');
|
||||
$this->assertTrue(SafeMarkup::isSafe($returned), 'String set with "all" provider is safe for default (html)');
|
||||
$returned = $this->safeMarkupSet('string2', 'css');
|
||||
$this->assertFalse(SafeMarkup::isSafe($returned), 'String set with "css" provider is not safe for default (html)');
|
||||
$returned = $this->safeMarkupSet('string3');
|
||||
$this->assertFalse(SafeMarkup::isSafe($returned, 'all'), 'String set with "html" provider is not safe for "all"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testSet().
|
||||
*
|
||||
* @see testSet()
|
||||
*/
|
||||
public function providerSet() {
|
||||
// Checks that invalid multi-byte sequences are rejected.
|
||||
$tests[] = array("Foo\xC0barbaz", '', 'SafeMarkup::checkPlain() rejects invalid sequence "Foo\xC0barbaz"', TRUE);
|
||||
$tests[] = array("Fooÿñ", 'SafeMarkup::set() accepts valid sequence "Fooÿñ"');
|
||||
$tests[] = array(new TextWrapper("Fooÿñ"), 'SafeMarkup::set() accepts valid sequence "Fooÿñ" in an object implementing __toString()');
|
||||
$tests[] = array("<div>", 'SafeMarkup::set() accepts HTML');
|
||||
// Checks that invalid multi-byte sequences are escaped.
|
||||
$tests[] = array(
|
||||
'Foo<6F>barbaz',
|
||||
'SafeMarkup::setMarkup() functions with valid sequence "Foo<6F>barbaz"',
|
||||
TRUE
|
||||
);
|
||||
$tests[] = array(
|
||||
"Fooÿñ",
|
||||
'SafeMarkup::setMarkup() functions with valid sequence "Fooÿñ"'
|
||||
);
|
||||
$tests[] = array("<div>", 'SafeMarkup::setMultiple() does not escape HTML');
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SafeMarkup::set() and SafeMarkup::isSafe() with different providers.
|
||||
* Tests SafeMarkup::setMultiple().
|
||||
* @dataProvider providerSet
|
||||
*
|
||||
* @covers ::isSafe
|
||||
* @param string $text
|
||||
* The text or object to provide to SafeMarkup::setMultiple().
|
||||
* @param string $message
|
||||
* The message to provide as output for the test.
|
||||
*
|
||||
* @covers ::setMultiple
|
||||
*/
|
||||
public function testStrategy() {
|
||||
$returned = SafeMarkup::set('string0', 'html');
|
||||
$this->assertTrue(SafeMarkup::isSafe($returned), 'String set with "html" provider is safe for default (html)');
|
||||
$returned = SafeMarkup::set('string1', 'all');
|
||||
$this->assertTrue(SafeMarkup::isSafe($returned), 'String set with "all" provider is safe for default (html)');
|
||||
$returned = SafeMarkup::set('string2', 'css');
|
||||
$this->assertFalse(SafeMarkup::isSafe($returned), 'String set with "css" provider is not safe for default (html)');
|
||||
$returned = SafeMarkup::set('string3');
|
||||
$this->assertFalse(SafeMarkup::isSafe($returned, 'all'), 'String set with "html" provider is not safe for "all"');
|
||||
public function testSet($text, $message) {
|
||||
SafeMarkup::setMultiple([$text => ['html' => TRUE]]);
|
||||
$this->assertTrue(SafeMarkup::isSafe($text), $message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -140,10 +168,10 @@ class SafeMarkupTest extends UnitTestCase {
|
|||
* @see testCheckPlain()
|
||||
*/
|
||||
function providerCheckPlain() {
|
||||
// Checks that invalid multi-byte sequences are rejected.
|
||||
$tests[] = array("Foo\xC0barbaz", '', 'SafeMarkup::checkPlain() rejects invalid sequence "Foo\xC0barbaz"', TRUE);
|
||||
$tests[] = array("\xc2\"", '', 'SafeMarkup::checkPlain() rejects invalid sequence "\xc2\""', TRUE);
|
||||
$tests[] = array("Fooÿñ", "Fooÿñ", 'SafeMarkup::checkPlain() accepts valid sequence "Fooÿñ"');
|
||||
// Checks that invalid multi-byte sequences are escaped.
|
||||
$tests[] = array("Foo\xC0barbaz", 'Foo<EFBFBD>barbaz', 'SafeMarkup::checkPlain() escapes invalid sequence "Foo\xC0barbaz"', TRUE);
|
||||
$tests[] = array("\xc2\"", '<EFBFBD>"', 'SafeMarkup::checkPlain() escapes invalid sequence "\xc2\""', TRUE);
|
||||
$tests[] = array("Fooÿñ", "Fooÿñ", 'SafeMarkup::checkPlain() does not escape valid sequence "Fooÿñ"');
|
||||
|
||||
// Checks that special characters are escaped.
|
||||
$tests[] = array("<script>", '<script>', 'SafeMarkup::checkPlain() escapes <script>');
|
||||
|
@ -160,7 +188,7 @@ class SafeMarkupTest extends UnitTestCase {
|
|||
*
|
||||
* @param string $string
|
||||
* The string to run through SafeMarkup::format().
|
||||
* @param string $args
|
||||
* @param string[] $args
|
||||
* The arguments to pass into SafeMarkup::format().
|
||||
* @param string $expected
|
||||
* The expected result from calling the function.
|
||||
|
@ -169,10 +197,14 @@ class SafeMarkupTest extends UnitTestCase {
|
|||
* @param bool $expected_is_safe
|
||||
* Whether the result is expected to be safe for HTML display.
|
||||
*/
|
||||
function testFormat($string, $args, $expected, $message, $expected_is_safe) {
|
||||
public function testFormat($string, array $args, $expected, $message, $expected_is_safe) {
|
||||
$result = SafeMarkup::format($string, $args);
|
||||
$this->assertEquals($expected, $result, $message);
|
||||
$this->assertEquals($expected_is_safe, SafeMarkup::isSafe($result), 'SafeMarkup::format correctly sets the result as safe or not safe.');
|
||||
|
||||
foreach ($args as $arg) {
|
||||
$this->assertSame($arg instanceof SafeMarkupTestSafeString, SafeMarkup::isSafe($arg));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,124 +215,11 @@ class SafeMarkupTest extends UnitTestCase {
|
|||
function providerFormat() {
|
||||
$tests[] = array('Simple text', array(), 'Simple text', 'SafeMarkup::format leaves simple text alone.', TRUE);
|
||||
$tests[] = array('Escaped text: @value', array('@value' => '<script>'), 'Escaped text: <script>', 'SafeMarkup::format replaces and escapes string.', TRUE);
|
||||
$tests[] = array('Escaped text: @value', array('@value' => SafeMarkup::set('<span>Safe HTML</span>')), 'Escaped text: <span>Safe HTML</span>', 'SafeMarkup::format does not escape an already safe string.', TRUE);
|
||||
$tests[] = array('Escaped text: @value', array('@value' => SafeMarkupTestSafeString::create('<span>Safe HTML</span>')), 'Escaped text: <span>Safe HTML</span>', 'SafeMarkup::format does not escape an already safe string.', TRUE);
|
||||
$tests[] = array('Placeholder text: %value', array('%value' => '<script>'), 'Placeholder text: <em class="placeholder"><script></em>', 'SafeMarkup::format replaces, escapes and themes string.', TRUE);
|
||||
$tests[] = array('Placeholder text: %value', array('%value' => SafeMarkup::set('<span>Safe HTML</span>')), 'Placeholder text: <em class="placeholder"><span>Safe HTML</span></em>', 'SafeMarkup::format does not escape an already safe string themed as a placeholder.', TRUE);
|
||||
$tests[] = array('Placeholder text: %value', array('%value' => SafeMarkupTestSafeString::create('<span>Safe HTML</span>')), 'Placeholder text: <em class="placeholder"><span>Safe HTML</span></em>', 'SafeMarkup::format does not escape an already safe string themed as a placeholder.', TRUE);
|
||||
$tests[] = array('Verbatim text: !value', array('!value' => '<script>'), 'Verbatim text: <script>', 'SafeMarkup::format replaces verbatim string as-is.', FALSE);
|
||||
$tests[] = array('Verbatim text: !value', array('!value' => SafeMarkup::set('<span>Safe HTML</span>')), 'Verbatim text: <span>Safe HTML</span>', 'SafeMarkup::format replaces verbatim string as-is.', TRUE);
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SafeMarkup::placeholder().
|
||||
*
|
||||
* @covers ::placeholder
|
||||
*/
|
||||
function testPlaceholder() {
|
||||
$this->assertEquals('<em class="placeholder">Some text</em>', SafeMarkup::placeholder('Some text'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SafeMarkup::replace().
|
||||
*
|
||||
* @dataProvider providerReplace
|
||||
* @covers ::replace
|
||||
*/
|
||||
public function testReplace($search, $replace, $subject, $expected, $is_safe) {
|
||||
$result = SafeMarkup::replace($search, $replace, $subject);
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals($is_safe, SafeMarkup::isSafe($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the interaction between the safe list and XSS filtering.
|
||||
*
|
||||
* @covers ::xssFilter
|
||||
* @covers ::escape
|
||||
*/
|
||||
public function testAdminXss() {
|
||||
// Use the predefined XSS admin tag list. This strips the <marquee> tags.
|
||||
$this->assertEquals('text', SafeMarkup::xssFilter('<marquee>text</marquee>', Xss::getAdminTagList()));
|
||||
$this->assertTrue(SafeMarkup::isSafe('text'), 'The string \'text\' is marked as safe.');
|
||||
|
||||
// This won't strip the <marquee> tags and the string with HTML will be
|
||||
// marked as safe.
|
||||
$filtered = SafeMarkup::xssFilter('<marquee>text</marquee>', array('marquee'));
|
||||
$this->assertEquals('<marquee>text</marquee>', $filtered);
|
||||
$this->assertTrue(SafeMarkup::isSafe('<marquee>text</marquee>'), 'The string \'<marquee>text</marquee>\' is marked as safe.');
|
||||
|
||||
// SafeMarkup::xssFilter() with the default tag list will strip the
|
||||
// <marquee> tag even though the string was marked safe above.
|
||||
$this->assertEquals('text', SafeMarkup::xssFilter('<marquee>text</marquee>'));
|
||||
|
||||
// SafeMarkup::escape() will not escape the markup tag since the string was
|
||||
// marked safe above.
|
||||
$this->assertEquals('<marquee>text</marquee>', SafeMarkup::escape($filtered));
|
||||
|
||||
// SafeMarkup::checkPlain() will escape the markup tag even though the
|
||||
// string was marked safe above.
|
||||
$this->assertEquals('<marquee>text</marquee>', SafeMarkup::checkPlain($filtered));
|
||||
|
||||
// Ensure that SafeMarkup::xssFilter strips all tags when passed an empty
|
||||
// array and uses the default tag list when not passed a tag list.
|
||||
$this->assertEquals('text', SafeMarkup::xssFilter('<em>text</em>', []));
|
||||
$this->assertEquals('<em>text</em>', SafeMarkup::xssFilter('<em>text</em>'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testReplace().
|
||||
*
|
||||
* @see testReplace()
|
||||
*/
|
||||
public function providerReplace() {
|
||||
$tests = [];
|
||||
|
||||
// Subject unsafe.
|
||||
$tests[] = [
|
||||
'<placeholder>',
|
||||
SafeMarkup::set('foo'),
|
||||
'<placeholder>bazqux',
|
||||
'foobazqux',
|
||||
FALSE,
|
||||
];
|
||||
|
||||
// All safe.
|
||||
$tests[] = [
|
||||
'<placeholder>',
|
||||
SafeMarkup::set('foo'),
|
||||
SafeMarkup::set('<placeholder>barbaz'),
|
||||
'foobarbaz',
|
||||
TRUE,
|
||||
];
|
||||
|
||||
// Safe subject, but should result in unsafe string because replacement is
|
||||
// unsafe.
|
||||
$tests[] = [
|
||||
'<placeholder>',
|
||||
'fubar',
|
||||
SafeMarkup::set('<placeholder>barbaz'),
|
||||
'fubarbarbaz',
|
||||
FALSE,
|
||||
];
|
||||
|
||||
// Array with all safe.
|
||||
$tests[] = [
|
||||
['<placeholder1>', '<placeholder2>', '<placeholder3>'],
|
||||
[SafeMarkup::set('foo'), SafeMarkup::set('bar'), SafeMarkup::set('baz')],
|
||||
SafeMarkup::set('<placeholder1><placeholder2><placeholder3>'),
|
||||
'foobarbaz',
|
||||
TRUE,
|
||||
];
|
||||
|
||||
// Array with unsafe replacement.
|
||||
$tests[] = [
|
||||
['<placeholder1>', '<placeholder2>', '<placeholder3>',],
|
||||
[SafeMarkup::set('bar'), SafeMarkup::set('baz'), 'qux'],
|
||||
SafeMarkup::set('<placeholder1><placeholder2><placeholder3>'),
|
||||
'barbazqux',
|
||||
FALSE,
|
||||
];
|
||||
$tests[] = array('Verbatim text: !value', array('!value' => SafeMarkupTestSafeString::create('<span>Safe HTML</span>')), 'Verbatim text: <span>Safe HTML</span>', 'SafeMarkup::format replaces verbatim string as-is.', TRUE);
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
@ -320,3 +239,13 @@ class SafeMarkupTestString {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks text as safe.
|
||||
*
|
||||
* SafeMarkupTestSafeString is used to mark text as safe because
|
||||
* SafeMarkup::$safeStrings is a global static that affects all tests.
|
||||
*/
|
||||
class SafeMarkupTestSafeString implements SafeStringInterface {
|
||||
use SafeStringTrait;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\UrlHelper;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
|
@ -94,7 +93,7 @@ class UrlHelperTest extends UnitTestCase {
|
|||
public function testValidAbsolute($url, $scheme) {
|
||||
$test_url = $scheme . '://' . $url;
|
||||
$valid_url = UrlHelper::isValid($test_url, TRUE);
|
||||
$this->assertTrue($valid_url, SafeMarkup::format('@url is a valid URL.', array('@url' => $test_url)));
|
||||
$this->assertTrue($valid_url, $test_url . ' is a valid URL.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -125,7 +124,7 @@ class UrlHelperTest extends UnitTestCase {
|
|||
public function testInvalidAbsolute($url, $scheme) {
|
||||
$test_url = $scheme . '://' . $url;
|
||||
$valid_url = UrlHelper::isValid($test_url, TRUE);
|
||||
$this->assertFalse($valid_url, SafeMarkup::format('@url is NOT a valid URL.', array('@url' => $test_url)));
|
||||
$this->assertFalse($valid_url, $test_url . ' is NOT a valid URL.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,7 +158,7 @@ class UrlHelperTest extends UnitTestCase {
|
|||
public function testValidRelative($url, $prefix) {
|
||||
$test_url = $prefix . $url;
|
||||
$valid_url = UrlHelper::isValid($test_url);
|
||||
$this->assertTrue($valid_url, SafeMarkup::format('@url is a valid URL.', array('@url' => $test_url)));
|
||||
$this->assertTrue($valid_url, $test_url . ' is a valid URL.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -190,7 +189,7 @@ class UrlHelperTest extends UnitTestCase {
|
|||
public function testInvalidRelative($url, $prefix) {
|
||||
$test_url = $prefix . $url;
|
||||
$valid_url = UrlHelper::isValid($test_url);
|
||||
$this->assertFalse($valid_url, SafeMarkup::format('@url is NOT a valid URL.', array('@url' => $test_url)));
|
||||
$this->assertFalse($valid_url, $test_url . ' is NOT a valid URL.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -381,8 +380,10 @@ class UrlHelperTest extends UnitTestCase {
|
|||
*/
|
||||
public function testFilterBadProtocol($uri, $expected, $protocols) {
|
||||
UrlHelper::setAllowedProtocols($protocols);
|
||||
$filtered = UrlHelper::filterBadProtocol($uri);
|
||||
$this->assertEquals($expected, $filtered);
|
||||
$this->assertEquals($expected, UrlHelper::filterBadProtocol($uri));
|
||||
// Multiple calls to UrlHelper::filterBadProtocol() do not cause double
|
||||
// escaping.
|
||||
$this->assertEquals($expected, UrlHelper::filterBadProtocol(UrlHelper::filterBadProtocol($uri)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -78,6 +78,11 @@ class VariableTest extends UnitTestCase {
|
|||
'"\'"',
|
||||
"'",
|
||||
),
|
||||
array(
|
||||
// Quotes with $ symbols.
|
||||
'"\$settings[\'foo\']"',
|
||||
'$settings[\'foo\']',
|
||||
),
|
||||
// Object.
|
||||
array(
|
||||
// A stdClass object.
|
||||
|
|
Reference in a new issue