Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176
This commit is contained in:
commit
9921556621
13277 changed files with 1459781 additions and 0 deletions
|
@ -0,0 +1,221 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\ArgumentsResolverTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility {
|
||||
|
||||
use Drupal\Component\Utility\ArgumentsResolver;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\Utility\ArgumentsResolver
|
||||
* @group Access
|
||||
*/
|
||||
class ArgumentsResolverTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getArgument() method.
|
||||
*
|
||||
* @dataProvider providerTestGetArgument
|
||||
*/
|
||||
public function testGetArgument($callable, $scalars, $objects, $wildcards, $expected) {
|
||||
$arguments = (new ArgumentsResolver($scalars, $objects, $wildcards))->getArguments($callable);
|
||||
$this->assertSame($expected, $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data to testGetArgument().
|
||||
*/
|
||||
public function providerTestGetArgument() {
|
||||
$data = [];
|
||||
|
||||
// Test an optional parameter with no provided value.
|
||||
$data[] = [
|
||||
function($foo = 'foo') {}, [], [], [] , ['foo'],
|
||||
];
|
||||
|
||||
// Test an optional parameter with a provided value.
|
||||
$data[] = [
|
||||
function($foo = 'foo') {}, ['foo' => 'bar'], [], [], ['bar'],
|
||||
];
|
||||
|
||||
// Test with a provided value.
|
||||
$data[] = [
|
||||
function($foo) {}, ['foo' => 'bar'], [], [], ['bar'],
|
||||
];
|
||||
|
||||
// Test with an explicitly NULL value.
|
||||
$data[] = [
|
||||
function($foo) {}, [], ['foo' => NULL], [], [NULL],
|
||||
];
|
||||
|
||||
// Test with a raw value that overrides the provided upcast value, since
|
||||
// it is not typehinted.
|
||||
$scalars = ['foo' => 'baz'];
|
||||
$objects = ['foo' => new \stdClass()];
|
||||
$data[] = [
|
||||
function($foo) {}, $scalars, $objects, [], ['baz'],
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getArgument() with an object.
|
||||
*/
|
||||
public function testGetArgumentObject() {
|
||||
$callable = function(\stdClass $object) {};
|
||||
|
||||
$object = new \stdClass();
|
||||
$arguments = (new ArgumentsResolver([], ['object' => $object], []))->getArguments($callable);
|
||||
$this->assertSame([$object], $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getArgument() with a wildcard object for a parameter with a custom name.
|
||||
*/
|
||||
public function testGetWildcardArgument() {
|
||||
$callable = function(\stdClass $custom_name) {};
|
||||
|
||||
$object = new \stdClass();
|
||||
$arguments = (new ArgumentsResolver([], [], [$object]))->getArguments($callable);
|
||||
$this->assertSame([$object], $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getArgument() with a Route, Request, and Account object.
|
||||
*/
|
||||
public function testGetArgumentOrder() {
|
||||
$a1 = $this->getMock('\Drupal\Tests\Component\Utility\TestInterface1');
|
||||
$a2 = $this->getMock('\Drupal\Tests\Component\Utility\TestClass');
|
||||
$a3 = $this->getMock('\Drupal\Tests\Component\Utility\TestInterface2');
|
||||
|
||||
$objects = [
|
||||
't1' => $a1,
|
||||
'tc' => $a2,
|
||||
];
|
||||
$wildcards = [$a3];
|
||||
$resolver = new ArgumentsResolver([], $objects, $wildcards);
|
||||
|
||||
$callable = function(TestInterface1 $t1, TestClass $tc, TestInterface2 $t2) {};
|
||||
$arguments = $resolver->getArguments($callable);
|
||||
$this->assertSame([$a1, $a2, $a3], $arguments);
|
||||
|
||||
// Test again, but with the arguments in a different order.
|
||||
$callable = function(TestInterface2 $t2, TestClass $tc, TestInterface1 $t1) {};
|
||||
$arguments = $resolver->getArguments($callable);
|
||||
$this->assertSame([$a3, $a2, $a1], $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getArgument() with a wildcard parameter with no typehint.
|
||||
*
|
||||
* Without the typehint, the wildcard object will not be passed to the callable.
|
||||
*
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage requires a value for the "$route" argument.
|
||||
*/
|
||||
public function testGetWildcardArgumentNoTypehint() {
|
||||
$a = $this->getMock('\Drupal\Tests\Component\Utility\TestInterface1');
|
||||
$wildcards = [$a];
|
||||
$resolver = new ArgumentsResolver([], [], $wildcards);
|
||||
|
||||
$callable = function($route) {};
|
||||
$arguments = $resolver->getArguments($callable);
|
||||
$this->assertNull($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getArgument() with a named parameter with no typehint and a value.
|
||||
*
|
||||
* Without the typehint, passing a value to a named parameter will still
|
||||
* receive the provided value.
|
||||
*/
|
||||
public function testGetArgumentRouteNoTypehintAndValue() {
|
||||
$scalars = ['route' => 'foo'];
|
||||
$resolver = new ArgumentsResolver($scalars, [], []);
|
||||
|
||||
$callable = function($route) {};
|
||||
$arguments = $resolver->getArguments($callable);
|
||||
$this->assertSame(['foo'], $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests handleUnresolvedArgument() for a scalar argument.
|
||||
*
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage requires a value for the "$foo" argument.
|
||||
*/
|
||||
public function testHandleNotUpcastedArgument() {
|
||||
$objects = ['foo' => 'bar'];
|
||||
$scalars = ['foo' => 'baz'];
|
||||
$resolver = new ArgumentsResolver($scalars, $objects, []);
|
||||
|
||||
$callable = function(\stdClass $foo) {};
|
||||
$arguments = $resolver->getArguments($callable);
|
||||
$this->assertNull($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests handleUnresolvedArgument() for missing arguments.
|
||||
*
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage requires a value for the "$foo" argument.
|
||||
*
|
||||
* @dataProvider providerTestHandleUnresolvedArgument
|
||||
*/
|
||||
public function testHandleUnresolvedArgument($callable) {
|
||||
$resolver = new ArgumentsResolver([], [], []);
|
||||
$arguments = $resolver->getArguments($callable);
|
||||
$this->assertNull($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data to testHandleUnresolvedArgument().
|
||||
*/
|
||||
public function providerTestHandleUnresolvedArgument() {
|
||||
$data = [];
|
||||
$data[] = [function($foo) {}];
|
||||
$data[] = [[new TestClass(), 'access']];
|
||||
$data[] = ['test_access_arguments_resolver_access'];
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a test class.
|
||||
*/
|
||||
class TestClass {
|
||||
public function access($foo) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a test interface.
|
||||
*/
|
||||
interface TestInterface1 {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a different test interface.
|
||||
*/
|
||||
interface TestInterface2 {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
function test_access_arguments_resolver_access($foo) {
|
||||
}
|
||||
}
|
65
core/tests/Drupal/Tests/Component/Utility/BytesTest.php
Normal file
65
core/tests/Drupal/Tests/Component/Utility/BytesTest.php
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\BytesTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\Bytes;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests bytes size parsing helper methods.
|
||||
*
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Bytes
|
||||
*/
|
||||
class BytesTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests \Drupal\Component\Utility\Bytes::toInt().
|
||||
*
|
||||
* @param int $size
|
||||
* The value for the size argument for
|
||||
* \Drupal\Component\Utility\Bytes::toInt().
|
||||
* @param int $expected_int
|
||||
* The expected return value from
|
||||
* \Drupal\Component\Utility\Bytes::toInt().
|
||||
*
|
||||
* @dataProvider providerTestToInt
|
||||
* @covers ::toInt
|
||||
*/
|
||||
public function testToInt($size, $expected_int) {
|
||||
$this->assertEquals($expected_int, Bytes::toInt($size));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for testToInt.
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays, each containing the argument for
|
||||
* \Drupal\Component\Utility\Bytes::toInt(): size, and the expected return
|
||||
* value.
|
||||
*/
|
||||
public function providerTestToInt() {
|
||||
return array(
|
||||
array('1', 1),
|
||||
array('1 byte', 1),
|
||||
array('1 KB' , Bytes::KILOBYTE),
|
||||
array('1 MB' , pow(Bytes::KILOBYTE, 2)),
|
||||
array('1 GB' , pow(Bytes::KILOBYTE, 3)),
|
||||
array('1 TB' , pow(Bytes::KILOBYTE, 4)),
|
||||
array('1 PB' , pow(Bytes::KILOBYTE, 5)),
|
||||
array('1 EB' , pow(Bytes::KILOBYTE, 6)),
|
||||
array('1 ZB' , pow(Bytes::KILOBYTE, 7)),
|
||||
array('1 YB' , pow(Bytes::KILOBYTE, 8)),
|
||||
array('23476892 bytes', 23476892),
|
||||
array('76MRandomStringThatShouldBeIgnoredByParseSize.', 79691776), // 76 MB
|
||||
array('76.24 Giggabyte', 81862076662), // 76.24 GB (with typo)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
126
core/tests/Drupal/Tests/Component/Utility/ColorTest.php
Normal file
126
core/tests/Drupal/Tests/Component/Utility/ColorTest.php
Normal file
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\ColorTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\Color;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests Color utility class conversions.
|
||||
*
|
||||
* @group Utility
|
||||
*/
|
||||
class ColorTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests Color::hexToRgb().
|
||||
*
|
||||
* @param string $value
|
||||
* The hex color value.
|
||||
* @param string $expected
|
||||
* The expected rgb color value.
|
||||
* @param bool $invalid
|
||||
* Whether this value is invalid and exception should be expected.
|
||||
*
|
||||
* @dataProvider providerTestHexToRgb
|
||||
*/
|
||||
public function testHexToRgb($value, $expected, $invalid = FALSE) {
|
||||
if ($invalid) {
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
}
|
||||
$this->assertSame($expected, Color::hexToRgb($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testHexToRgb().
|
||||
*
|
||||
* @see testHexToRgb()
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays containing:
|
||||
* - The hex color value.
|
||||
* - The rgb color array value.
|
||||
* - (optional) Boolean indicating invalid status. Defaults to FALSE.
|
||||
*/
|
||||
public function providerTestHexToRgb() {
|
||||
$invalid = array();
|
||||
// Any invalid arguments should throw an exception.
|
||||
foreach (array('', '-1', '1', '12', '12345', '1234567', '123456789', '123456789a', 'foo') as $value) {
|
||||
$invalid[] = array($value, '', TRUE);
|
||||
}
|
||||
// Duplicate all invalid value tests with additional '#' prefix.
|
||||
// The '#' prefix inherently turns the data type into a string.
|
||||
foreach ($invalid as $value) {
|
||||
$invalid[] = array('#' . $value[0], '', TRUE);
|
||||
}
|
||||
// Add invalid data types (hex value must be a string).
|
||||
foreach (array(
|
||||
1, 12, 1234, 12345, 123456, 1234567, 12345678, 123456789, 123456789,
|
||||
-1, PHP_INT_MAX, PHP_INT_MAX + 1, -PHP_INT_MAX, 0x0, 0x010
|
||||
) as $value) {
|
||||
$invalid[] = array($value, '', TRUE);
|
||||
}
|
||||
// And some valid values.
|
||||
$valid = array(
|
||||
// Shorthands without alpha.
|
||||
array('hex' => '#000', 'rgb' => array('red' => 0, 'green' => 0, 'blue' => 0)),
|
||||
array('hex' => '#fff', 'rgb' => array('red' => 255, 'green' => 255, 'blue' => 255)),
|
||||
array('hex' => '#abc', 'rgb' => array('red' => 170, 'green' => 187, 'blue' => 204)),
|
||||
array('hex' => 'cba', 'rgb' => array('red' => 204, 'green' => 187, 'blue' => 170)),
|
||||
// Full without alpha.
|
||||
array('hex' => '#000000', 'rgb' => array('red' => 0, 'green' => 0, 'blue' => 0)),
|
||||
array('hex' => '#ffffff', 'rgb' => array('red' => 255, 'green' => 255, 'blue' => 255)),
|
||||
array('hex' => '#010203', 'rgb' => array('red' => 1, 'green' => 2, 'blue' => 3)),
|
||||
);
|
||||
return array_merge($invalid, $valid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Color::rgbToHex().
|
||||
*
|
||||
* @param string $value
|
||||
* The rgb color value.
|
||||
* @param string $expected
|
||||
* The expected hex color value.
|
||||
*
|
||||
* @dataProvider providerTestRbgToHex
|
||||
*/
|
||||
public function testRgbToHex($value, $expected) {
|
||||
$this->assertSame($expected, Color::rgbToHex($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testRgbToHex().
|
||||
*
|
||||
* @see testRgbToHex()
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays containing:
|
||||
* - The rgb color array value.
|
||||
* - The hex color value.
|
||||
*/
|
||||
public function providerTestRbgToHex() {
|
||||
// Input using named RGB array (e.g., as returned by Color::hexToRgb()).
|
||||
$tests = array(
|
||||
array(array('red' => 0, 'green' => 0, 'blue' => 0), '#000000'),
|
||||
array(array('red' => 255, 'green' => 255, 'blue' => 255), '#ffffff'),
|
||||
array(array('red' => 119, 'green' => 119, 'blue' => 119), '#777777'),
|
||||
array(array('red' => 1, 'green' => 2, 'blue' => 3), '#010203'),
|
||||
);
|
||||
// Input using indexed RGB array (e.g.: array(10, 10, 10)).
|
||||
foreach ($tests as $test) {
|
||||
$tests[] = array(array_values($test[0]), $test[1]);
|
||||
}
|
||||
// Input using CSS RGB string notation (e.g.: 10, 10, 10).
|
||||
foreach ($tests as $test) {
|
||||
$tests[] = array(implode(', ', $test[0]), $test[1]);
|
||||
}
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
155
core/tests/Drupal/Tests/Component/Utility/CryptTest.php
Normal file
155
core/tests/Drupal/Tests/Component/Utility/CryptTest.php
Normal file
|
@ -0,0 +1,155 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\CryptTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
|
||||
/**
|
||||
* Tests random byte generation.
|
||||
*
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Crypt
|
||||
*/
|
||||
class CryptTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests random byte generation.
|
||||
*
|
||||
* @covers ::randomBytes
|
||||
*/
|
||||
public function testRandomBytes() {
|
||||
for ($i = 1; $i < 10; $i++) {
|
||||
$count = rand(10, 10000);
|
||||
// Check that different values are being generated.
|
||||
$this->assertNotEquals(Crypt::randomBytes($count), Crypt::randomBytes($count));
|
||||
// Check the length.
|
||||
$this->assertEquals(strlen(Crypt::randomBytes($count)), $count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests hash generation.
|
||||
*
|
||||
* @dataProvider providerTestHashBase64
|
||||
* @covers ::hashBase64
|
||||
*
|
||||
* @param string $data
|
||||
* Data to hash.
|
||||
* @param string $expected_hash
|
||||
* Expected result from hashing $data.
|
||||
*/
|
||||
public function testHashBase64($data, $expected_hash) {
|
||||
$hash = Crypt::hashBase64($data);
|
||||
$this->assertEquals($expected_hash, $hash, 'The correct hash was not calculated.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests HMAC generation.
|
||||
*
|
||||
* @dataProvider providerTestHmacBase64
|
||||
* @covers ::hmacBase64
|
||||
*
|
||||
* @param string $data
|
||||
* Data to hash.
|
||||
* @param string $key
|
||||
* Key to use in hashing process.
|
||||
* @param string $expected_hmac
|
||||
* Expected result from hashing $data using $key.
|
||||
*/
|
||||
public function testHmacBase64($data, $key, $expected_hmac) {
|
||||
$hmac = Crypt::hmacBase64($data, $key);
|
||||
$this->assertEquals($expected_hmac, $hmac, 'The correct hmac was not calculated.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the hmacBase64 method with invalid parameters.
|
||||
*
|
||||
* @dataProvider providerTestHmacBase64Invalid
|
||||
* @expectedException InvalidArgumentException
|
||||
* @covers ::hmacBase64
|
||||
*
|
||||
* @param string $data
|
||||
* Data to hash.
|
||||
* @param string $key
|
||||
* Key to use in hashing process.
|
||||
*/
|
||||
public function testHmacBase64Invalid($data, $key) {
|
||||
Crypt::hmacBase64($data, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testHashBase64().
|
||||
*
|
||||
* @return array Test data.
|
||||
*/
|
||||
public function providerTestHashBase64() {
|
||||
return array(
|
||||
array(
|
||||
'data' => 'The SHA (Secure Hash Algorithm) is one of a number of cryptographic hash functions. A cryptographic hash is like a signature for a text or a data file. SHA-256 algorithm generates an almost-unique, fixed size 256-bit (32-byte) hash. Hash is a one way function – it cannot be decrypted back. This makes it suitable for password validation, challenge hash authentication, anti-tamper, digital signatures.',
|
||||
'expectedHash' => '034rT6smZAVRxpq8O98cFFNLIVx_Ph1EwLZQKcmRR_s',
|
||||
),
|
||||
array(
|
||||
'data' => 'SHA-256 is one of the successor hash functions to SHA-1, and is one of the strongest hash functions available.',
|
||||
'expected_hash' => 'yuqkDDYqprL71k4xIb6K6D7n76xldO4jseRhEkEE6SI',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testHmacBase64().
|
||||
*
|
||||
* @return array Test data.
|
||||
*/
|
||||
public function providerTestHmacBase64() {
|
||||
return array(
|
||||
array(
|
||||
'data' => 'Calculates a base-64 encoded, URL-safe sha-256 hmac.',
|
||||
'key' => 'secret-key',
|
||||
'expected_hmac' => '2AaH63zwjhekWZlEpAiufyfhAHIzbQhl9Hd9oCi3_c8',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testHmacBase64().
|
||||
*
|
||||
* @return array Test data.
|
||||
*/
|
||||
public function providerTestHmacBase64Invalid() {
|
||||
return array(
|
||||
array(new \stdClass(), new \stdClass()),
|
||||
array(new \stdClass(), 'string'),
|
||||
array(new \stdClass(), 1),
|
||||
array(new \stdClass(), 0),
|
||||
array(NULL, new \stdClass()),
|
||||
array('string', new \stdClass()),
|
||||
array(1, new \stdClass()),
|
||||
array(0, new \stdClass()),
|
||||
array(array(), array()),
|
||||
array(array(), NULL),
|
||||
array(array(), 'string'),
|
||||
array(array(), 1),
|
||||
array(array(), 0),
|
||||
array(NULL, array()),
|
||||
array(1, array()),
|
||||
array(0, array()),
|
||||
array('string', array()),
|
||||
array(array(), NULL),
|
||||
array(NULL, NULL),
|
||||
array(NULL, 'string'),
|
||||
array(NULL, 1),
|
||||
array(NULL, 0),
|
||||
array(1, NULL),
|
||||
array(0, NULL),
|
||||
array('string', NULL),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\EnvironmentTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\Environment;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Test PHP Environment helper methods.
|
||||
*
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Environment
|
||||
*/
|
||||
class EnvironmentTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests \Drupal\Component\Utility\Environment::checkMemoryLimit().
|
||||
*
|
||||
* @dataProvider providerTestCheckMemoryLimit
|
||||
* @covers ::checkMemoryLimit
|
||||
*
|
||||
* @param string $required
|
||||
* The required memory argument for
|
||||
* \Drupal\Component\Utility\Environment::checkMemoryLimit().
|
||||
* @param string $custom_memory_limit
|
||||
* The custom memory limit argument for
|
||||
* \Drupal\Component\Utility\Environment::checkMemoryLimit().
|
||||
* @param bool $expected
|
||||
* The expected return value from
|
||||
* \Drupal\Component\Utility\Environment::checkMemoryLimit().
|
||||
*/
|
||||
public function testCheckMemoryLimit($required, $custom_memory_limit, $expected) {
|
||||
$actual = Environment::checkMemoryLimit($required, $custom_memory_limit);
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for testCheckMemoryLimit().
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays, each containing the arguments for
|
||||
* \Drupal\Component\Utility\Environment::checkMemoryLimit():
|
||||
* required and memory_limit, and the expected return value.
|
||||
*/
|
||||
public function providerTestCheckMemoryLimit() {
|
||||
$memory_limit = ini_get('memory_limit');
|
||||
$twice_avail_memory = ($memory_limit * 2) . 'MB';
|
||||
|
||||
return array(
|
||||
// Minimal amount of memory should be available.
|
||||
array('30MB', NULL, TRUE),
|
||||
// Exceed a custom (unlimited) memory limit.
|
||||
array($twice_avail_memory, -1, TRUE),
|
||||
// Exceed a custom memory limit.
|
||||
array('30MB', '16MB', FALSE),
|
||||
// Available = required.
|
||||
array('30MB', '30MB', TRUE),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
262
core/tests/Drupal/Tests/Component/Utility/HtmlTest.php
Normal file
262
core/tests/Drupal/Tests/Component/Utility/HtmlTest.php
Normal file
|
@ -0,0 +1,262 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\HtmlTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests \Drupal\Component\Utility\Html.
|
||||
*
|
||||
* @group Common
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Html
|
||||
*/
|
||||
class HtmlTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$property = new \ReflectionProperty('Drupal\Component\Utility\Html', 'seenIdsInit');
|
||||
$property->setAccessible(TRUE);
|
||||
$property->setValue(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Html::cleanCssIdentifier() method.
|
||||
*
|
||||
* @param string $expected
|
||||
* The expected result.
|
||||
* @param string $source
|
||||
* The string being transformed to an ID.
|
||||
* @param array|null $filter
|
||||
* (optional) An array of string replacements to use on the identifier. If
|
||||
* NULL, no filter will be passed and a default will be used.
|
||||
*
|
||||
* @dataProvider providerTestCleanCssIdentifier
|
||||
*
|
||||
* @covers ::cleanCssIdentifier
|
||||
*/
|
||||
public function testCleanCssIdentifier($expected, $source, $filter = NULL) {
|
||||
if ($filter !== NULL) {
|
||||
$this->assertSame($expected, Html::cleanCssIdentifier($source, $filter));
|
||||
}
|
||||
else {
|
||||
$this->assertSame($expected, Html::cleanCssIdentifier($source));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testCleanCssIdentifier().
|
||||
*
|
||||
* @return array
|
||||
* Test data.
|
||||
*/
|
||||
public function providerTestCleanCssIdentifier() {
|
||||
$id1 = 'abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789';
|
||||
$id2 = '¡¢£¤¥';
|
||||
$id3 = 'css__identifier__with__double__underscores';
|
||||
return array(
|
||||
// Verify that no valid ASCII characters are stripped from the identifier.
|
||||
array($id1, $id1, array()),
|
||||
// Verify that valid UTF-8 characters are not stripped from the identifier.
|
||||
array($id2, $id2, array()),
|
||||
// Verify that invalid characters (including non-breaking space) are stripped from the identifier.
|
||||
array($id3, $id3),
|
||||
// Verify that double underscores are not stripped from the identifier.
|
||||
array('invalididentifier', 'invalid !"#$%&\'()*+,./:;<=>?@[\\]^`{|}~ identifier', array()),
|
||||
// Verify that an identifier starting with a digit is replaced.
|
||||
array('_cssidentifier', '1cssidentifier', array()),
|
||||
// Verify that an identifier starting with a hyphen followed by a digit is
|
||||
// replaced.
|
||||
array('__cssidentifier', '-1cssidentifier', array()),
|
||||
// Verify that an identifier starting with two hyphens is replaced.
|
||||
array('__cssidentifier', '--cssidentifier', array())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that Html::getClass() cleans the class name properly.
|
||||
*
|
||||
* @coversDefaultClass ::getClass
|
||||
*/
|
||||
public function testHtmlClass() {
|
||||
// Verify Drupal coding standards are enforced.
|
||||
$this->assertSame(Html::getClass('CLASS NAME_[Ü]'), 'class-name--ü', 'Enforce Drupal coding standards.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Html::getUniqueId() method.
|
||||
*
|
||||
* @param string $expected
|
||||
* The expected result.
|
||||
* @param string $source
|
||||
* The string being transformed to an ID.
|
||||
* @param bool $reset
|
||||
* (optional) If TRUE, reset the list of seen IDs. Defaults to FALSE.
|
||||
*
|
||||
* @dataProvider providerTestHtmlGetUniqueId
|
||||
*
|
||||
* @covers ::getUniqueId
|
||||
*/
|
||||
public function testHtmlGetUniqueId($expected, $source, $reset = FALSE) {
|
||||
if ($reset) {
|
||||
Html::resetSeenIds();
|
||||
}
|
||||
$this->assertSame($expected, Html::getUniqueId($source));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testHtmlGetId().
|
||||
*
|
||||
* @return array
|
||||
* Test data.
|
||||
*/
|
||||
public function providerTestHtmlGetUniqueId() {
|
||||
$id = 'abcdefghijklmnopqrstuvwxyz-0123456789';
|
||||
return array(
|
||||
// Verify that letters, digits, and hyphens are not stripped from the ID.
|
||||
array($id, $id),
|
||||
// Verify that invalid characters are stripped from the ID.
|
||||
array('invalididentifier', 'invalid,./:@\\^`{Üidentifier'),
|
||||
// Verify Drupal coding standards are enforced.
|
||||
array('id-name-1', 'ID NAME_[1]'),
|
||||
// Verify that a repeated ID is made unique.
|
||||
array('test-unique-id', 'test-unique-id', TRUE),
|
||||
array('test-unique-id--2', 'test-unique-id'),
|
||||
array('test-unique-id--3', 'test-unique-id'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Html::getUniqueId() method.
|
||||
*
|
||||
* @param string $expected
|
||||
* The expected result.
|
||||
* @param string $source
|
||||
* The string being transformed to an ID.
|
||||
*
|
||||
* @dataProvider providerTestHtmlGetUniqueIdWithAjaxIds
|
||||
*
|
||||
* @covers ::getUniqueId
|
||||
*/
|
||||
public function testHtmlGetUniqueIdWithAjaxIds($expected, $source) {
|
||||
Html::setIsAjax(TRUE);
|
||||
$id = Html::getUniqueId($source);
|
||||
|
||||
// Note, we truncate two hyphens at the end.
|
||||
// @see \Drupal\Component\Utility\Html::getId()
|
||||
if (strpos($source, '--') !== FALSE) {
|
||||
$random_suffix = substr($id, strlen($source) + 1);
|
||||
}
|
||||
else {
|
||||
$random_suffix = substr($id, strlen($source) + 2);
|
||||
}
|
||||
$expected = $expected . $random_suffix;
|
||||
$this->assertSame($expected, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testHtmlGetId().
|
||||
*
|
||||
* @return array
|
||||
* Test data.
|
||||
*/
|
||||
public function providerTestHtmlGetUniqueIdWithAjaxIds() {
|
||||
return array(
|
||||
array('test-unique-id1--', 'test-unique-id1'),
|
||||
// Note, we truncate two hyphens at the end.
|
||||
// @see \Drupal\Component\Utility\Html::getId()
|
||||
array('test-unique-id1---', 'test-unique-id1--'),
|
||||
array('test-unique-id2--', 'test-unique-id2'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Html::getUniqueId() method.
|
||||
*
|
||||
* @param string $expected
|
||||
* The expected result.
|
||||
* @param string $source
|
||||
* The string being transformed to an ID.
|
||||
*
|
||||
* @dataProvider providerTestHtmlGetId
|
||||
*
|
||||
* @covers ::getId
|
||||
*/
|
||||
public function testHtmlGetId($expected, $source) {
|
||||
Html::setIsAjax(FALSE);
|
||||
$this->assertSame($expected, Html::getId($source));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testHtmlGetId().
|
||||
*
|
||||
* @return array
|
||||
* Test data.
|
||||
*/
|
||||
public function providerTestHtmlGetId() {
|
||||
$id = 'abcdefghijklmnopqrstuvwxyz-0123456789';
|
||||
return array(
|
||||
// Verify that letters, digits, and hyphens are not stripped from the ID.
|
||||
array($id, $id),
|
||||
// Verify that invalid characters are stripped from the ID.
|
||||
array('invalididentifier', 'invalid,./:@\\^`{Üidentifier'),
|
||||
// Verify Drupal coding standards are enforced.
|
||||
array('id-name-1', 'ID NAME_[1]'),
|
||||
// Verify that a repeated ID is made unique.
|
||||
array('test-unique-id', 'test-unique-id'),
|
||||
array('test-unique-id', 'test-unique-id'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Html::decodeEntities().
|
||||
*
|
||||
* @dataProvider providerDecodeEntities
|
||||
* @covers ::decodeEntities
|
||||
*/
|
||||
public function testDecodeEntities($text, $expected) {
|
||||
$this->assertEquals($expected, Html::decodeEntities($text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testDecodeEntities().
|
||||
*
|
||||
* @see testCheckPlain()
|
||||
*/
|
||||
public function providerDecodeEntities() {
|
||||
return array(
|
||||
array('Drupal', 'Drupal'),
|
||||
array('<script>', '<script>'),
|
||||
array('<script>', '<script>'),
|
||||
array('<script>', '<script>'),
|
||||
array('&lt;script&gt;', '<script>'),
|
||||
array('"', '"'),
|
||||
array('"', '"'),
|
||||
array('&#34;', '"'),
|
||||
array('"', '"'),
|
||||
array('&quot;', '"'),
|
||||
array("'", "'"),
|
||||
array(''', "'"),
|
||||
array('&#39;', '''),
|
||||
array('©', '©'),
|
||||
array('©', '©'),
|
||||
array('©', '©'),
|
||||
array('→', '→'),
|
||||
array('→', '→'),
|
||||
array('➼', '➼'),
|
||||
array('➼', '➼'),
|
||||
array('€', '€'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
164
core/tests/Drupal/Tests/Component/Utility/ImageTest.php
Normal file
164
core/tests/Drupal/Tests/Component/Utility/ImageTest.php
Normal file
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\ImageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\Image;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Image
|
||||
* @group Image
|
||||
*/
|
||||
class ImageTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests all control flow branches in image_dimensions_scale().
|
||||
*
|
||||
* @dataProvider providerTestScaleDimensions
|
||||
*/
|
||||
public function testScaleDimensions($input, $output) {
|
||||
// Process the test dataset.
|
||||
$return_value = Image::scaleDimensions($input['dimensions'], $input['width'], $input['height'], $input['upscale']);
|
||||
|
||||
// Check the width.
|
||||
$this->assertEquals($output['dimensions']['width'], $input['dimensions']['width'], sprintf('Computed width (%s) does not equal expected width (%s)', $output['dimensions']['width'], $input['dimensions']['width']));
|
||||
|
||||
// Check the height.
|
||||
$this->assertEquals($output['dimensions']['height'], $input['dimensions']['height'], sprintf('Computed height (%s) does not equal expected height (%s)', $output['dimensions']['height'], $input['dimensions']['height']));
|
||||
|
||||
// Check the return value.
|
||||
$this->assertEquals($output['return_value'], $return_value, 'Incorrect return value.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for image dimension scale tests.
|
||||
*
|
||||
* @return array
|
||||
* Keyed array containing:
|
||||
* - 'input' - Array which contains input for
|
||||
* Image::scaleDimensions().
|
||||
* - 'output' - Array which contains expected output after passing
|
||||
* through Image::scaleDimensions. Also contains a boolean
|
||||
* 'return_value' which should match the expected return value.
|
||||
*
|
||||
* @see testScaleDimensions()
|
||||
*/
|
||||
public function providerTestScaleDimensions() {
|
||||
// Define input / output datasets to test different branch conditions.
|
||||
$tests = array();
|
||||
|
||||
// Test branch conditions:
|
||||
// - No height.
|
||||
// - Upscale, don't need to upscale.
|
||||
$tests[] = array(
|
||||
'input' => array(
|
||||
'dimensions' => array(
|
||||
'width' => 1000,
|
||||
'height' => 2000,
|
||||
),
|
||||
'width' => 200,
|
||||
'height' => NULL,
|
||||
'upscale' => TRUE,
|
||||
),
|
||||
'output' => array(
|
||||
'dimensions' => array(
|
||||
'width' => 200,
|
||||
'height' => 400,
|
||||
),
|
||||
'return_value' => TRUE,
|
||||
),
|
||||
);
|
||||
|
||||
// Test branch conditions:
|
||||
// - No width.
|
||||
// - Don't upscale, don't need to upscale.
|
||||
$tests[] = array(
|
||||
'input' => array(
|
||||
'dimensions' => array(
|
||||
'width' => 1000,
|
||||
'height' => 800,
|
||||
),
|
||||
'width' => NULL,
|
||||
'height' => 140,
|
||||
'upscale' => FALSE,
|
||||
),
|
||||
'output' => array(
|
||||
'dimensions' => array(
|
||||
'width' => 175,
|
||||
'height' => 140,
|
||||
),
|
||||
'return_value' => TRUE,
|
||||
),
|
||||
);
|
||||
|
||||
// Test branch conditions:
|
||||
// - Source aspect ratio greater than target.
|
||||
// - Upscale, need to upscale.
|
||||
$tests[] = array(
|
||||
'input' => array(
|
||||
'dimensions' => array(
|
||||
'width' => 8,
|
||||
'height' => 20,
|
||||
),
|
||||
'width' => 200,
|
||||
'height' => 140,
|
||||
'upscale' => TRUE,
|
||||
),
|
||||
'output' => array(
|
||||
'dimensions' => array(
|
||||
'width' => 56,
|
||||
'height' => 140,
|
||||
),
|
||||
'return_value' => TRUE,
|
||||
),
|
||||
);
|
||||
|
||||
// Test branch condition: target aspect ratio greater than source.
|
||||
$tests[] = array(
|
||||
'input' => array(
|
||||
'dimensions' => array(
|
||||
'width' => 2000,
|
||||
'height' => 800,
|
||||
),
|
||||
'width' => 200,
|
||||
'height' => 140,
|
||||
'upscale' => FALSE,
|
||||
),
|
||||
'output' => array(
|
||||
'dimensions' => array(
|
||||
'width' => 200,
|
||||
'height' => 80,
|
||||
),
|
||||
'return_value' => TRUE,
|
||||
),
|
||||
);
|
||||
|
||||
// Test branch condition: don't upscale, need to upscale.
|
||||
$tests[] = array(
|
||||
'input' => array(
|
||||
'dimensions' => array(
|
||||
'width' => 100,
|
||||
'height' => 50,
|
||||
),
|
||||
'width' => 200,
|
||||
'height' => 140,
|
||||
'upscale' => FALSE,
|
||||
),
|
||||
'output' => array(
|
||||
'dimensions' => array(
|
||||
'width' => 100,
|
||||
'height' => 50,
|
||||
),
|
||||
'return_value' => FALSE,
|
||||
),
|
||||
);
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
262
core/tests/Drupal/Tests/Component/Utility/NestedArrayTest.php
Normal file
262
core/tests/Drupal/Tests/Component/Utility/NestedArrayTest.php
Normal file
|
@ -0,0 +1,262 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\NestedArrayTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\Utility\NestedArray
|
||||
* @group Utility
|
||||
*/
|
||||
class NestedArrayTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Form array to check.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* Array of parents for the nested element.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $parents;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a form structure with a nested element.
|
||||
$this->form['details']['element'] = array(
|
||||
'#value' => 'Nested element',
|
||||
);
|
||||
|
||||
// Set up parent array.
|
||||
$this->parents = array('details', 'element');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getting nested array values.
|
||||
*
|
||||
* @covers ::getValue
|
||||
*/
|
||||
public function testGetValue() {
|
||||
// Verify getting a value of a nested element.
|
||||
$value = NestedArray::getValue($this->form, $this->parents);
|
||||
$this->assertSame('Nested element', $value['#value'], 'Nested element value found.');
|
||||
|
||||
// Verify changing a value of a nested element by reference.
|
||||
$value = &NestedArray::getValue($this->form, $this->parents);
|
||||
$value['#value'] = 'New value';
|
||||
$value = NestedArray::getValue($this->form, $this->parents);
|
||||
$this->assertSame('New value', $value['#value'], 'Nested element value was changed by reference.');
|
||||
$this->assertSame('New value', $this->form['details']['element']['#value'], 'Nested element value was changed by reference.');
|
||||
|
||||
// Verify that an existing key is reported back.
|
||||
$key_exists = NULL;
|
||||
NestedArray::getValue($this->form, $this->parents, $key_exists);
|
||||
$this->assertTrue($key_exists, 'Existing key found.');
|
||||
|
||||
// Verify that a non-existing key is reported back and throws no errors.
|
||||
$key_exists = NULL;
|
||||
$parents = $this->parents;
|
||||
$parents[] = 'foo';
|
||||
NestedArray::getValue($this->form, $parents, $key_exists);
|
||||
$this->assertFalse($key_exists, 'Non-existing key not found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests setting nested array values.
|
||||
*
|
||||
* @covers ::setValue
|
||||
*/
|
||||
public function testSetValue() {
|
||||
$new_value = array(
|
||||
'#value' => 'New value',
|
||||
'#required' => TRUE,
|
||||
);
|
||||
|
||||
// Verify setting the value of a nested element.
|
||||
NestedArray::setValue($this->form, $this->parents, $new_value);
|
||||
$this->assertSame('New value', $this->form['details']['element']['#value'], 'Changed nested element value found.');
|
||||
$this->assertTrue($this->form['details']['element']['#required'], 'New nested element value found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests force-setting values.
|
||||
*
|
||||
* @covers ::setValue
|
||||
*/
|
||||
public function testSetValueForce() {
|
||||
$new_value = array(
|
||||
'one',
|
||||
);
|
||||
$this->form['details']['non-array-parent'] = 'string';
|
||||
$parents = array('details', 'non-array-parent', 'child');
|
||||
NestedArray::setValue($this->form, $parents, $new_value, TRUE);
|
||||
$this->assertSame($new_value, $this->form['details']['non-array-parent']['child'], 'The nested element was not forced to the new value.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests unsetting nested array values.
|
||||
*
|
||||
* @covers ::unsetValue
|
||||
*/
|
||||
public function testUnsetValue() {
|
||||
// Verify unsetting a non-existing nested element throws no errors and the
|
||||
// non-existing key is properly reported.
|
||||
$key_existed = NULL;
|
||||
$parents = $this->parents;
|
||||
$parents[] = 'foo';
|
||||
NestedArray::unsetValue($this->form, $parents, $key_existed);
|
||||
$this->assertTrue(isset($this->form['details']['element']['#value']), 'Outermost nested element key still exists.');
|
||||
$this->assertFalse($key_existed, 'Non-existing key not found.');
|
||||
|
||||
// Verify unsetting a nested element.
|
||||
$key_existed = NULL;
|
||||
NestedArray::unsetValue($this->form, $this->parents, $key_existed);
|
||||
$this->assertFalse(isset($this->form['details']['element']), 'Removed nested element not found.');
|
||||
$this->assertTrue($key_existed, 'Existing key was found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests existence of array key.
|
||||
*/
|
||||
public function testKeyExists() {
|
||||
// Verify that existing key is found.
|
||||
$this->assertTrue(NestedArray::keyExists($this->form, $this->parents), 'Nested key found.');
|
||||
|
||||
// Verify that non-existing keys are not found.
|
||||
$parents = $this->parents;
|
||||
$parents[] = 'foo';
|
||||
$this->assertFalse(NestedArray::keyExists($this->form, $parents), 'Non-existing nested key not found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests NestedArray::mergeDeepArray().
|
||||
*
|
||||
* @covers ::mergeDeep
|
||||
* @covers ::mergeDeepArray
|
||||
*/
|
||||
public function testMergeDeepArray() {
|
||||
$link_options_1 = array(
|
||||
'fragment' => 'x',
|
||||
'attributes' => array('title' => 'X', 'class' => array('a', 'b')),
|
||||
'language' => 'en',
|
||||
);
|
||||
$link_options_2 = array(
|
||||
'fragment' => 'y',
|
||||
'attributes' => array('title' => 'Y', 'class' => array('c', 'd')),
|
||||
'absolute' => TRUE,
|
||||
);
|
||||
$expected = array(
|
||||
'fragment' => 'y',
|
||||
'attributes' => array('title' => 'Y', 'class' => array('a', 'b', 'c', 'd')),
|
||||
'language' => 'en',
|
||||
'absolute' => TRUE,
|
||||
);
|
||||
$this->assertSame($expected, NestedArray::mergeDeepArray(array($link_options_1, $link_options_2)), 'NestedArray::mergeDeepArray() returned a properly merged array.');
|
||||
// Test wrapper function, NestedArray::mergeDeep().
|
||||
$this->assertSame($expected, NestedArray::mergeDeep($link_options_1, $link_options_2), 'NestedArray::mergeDeep() returned a properly merged array.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that arrays with implicit keys are appended, not merged.
|
||||
*
|
||||
* @covers ::mergeDeepArray
|
||||
*/
|
||||
public function testMergeImplicitKeys() {
|
||||
$a = array(
|
||||
'subkey' => array('X', 'Y'),
|
||||
);
|
||||
$b = array(
|
||||
'subkey' => array('X'),
|
||||
);
|
||||
|
||||
// Drupal core behavior.
|
||||
$expected = array(
|
||||
'subkey' => array('X', 'Y', 'X'),
|
||||
);
|
||||
$actual = NestedArray::mergeDeepArray(array($a, $b));
|
||||
$this->assertSame($expected, $actual, 'drupal_array_merge_deep() creates new numeric keys in the implicit sequence.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that even with explicit keys, values are appended, not merged.
|
||||
*
|
||||
* @covers ::mergeDeepArray
|
||||
*/
|
||||
public function testMergeExplicitKeys() {
|
||||
$a = array(
|
||||
'subkey' => array(
|
||||
0 => 'A',
|
||||
1 => 'B',
|
||||
),
|
||||
);
|
||||
$b = array(
|
||||
'subkey' => array(
|
||||
0 => 'C',
|
||||
1 => 'D',
|
||||
),
|
||||
);
|
||||
|
||||
// Drupal core behavior.
|
||||
$expected = array(
|
||||
'subkey' => array(
|
||||
0 => 'A',
|
||||
1 => 'B',
|
||||
2 => 'C',
|
||||
3 => 'D',
|
||||
),
|
||||
);
|
||||
$actual = NestedArray::mergeDeepArray(array($a, $b));
|
||||
$this->assertSame($expected, $actual, 'drupal_array_merge_deep() creates new numeric keys in the explicit sequence.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that array keys values on the first array are ignored when merging.
|
||||
*
|
||||
* Even if the initial ordering would place the data from the second array
|
||||
* before those in the first one, they are still appended, and the keys on
|
||||
* the first array are deleted and regenerated.
|
||||
*
|
||||
* @covers ::mergeDeepArray
|
||||
*/
|
||||
public function testMergeOutOfSequenceKeys() {
|
||||
$a = array(
|
||||
'subkey' => array(
|
||||
10 => 'A',
|
||||
30 => 'B',
|
||||
),
|
||||
);
|
||||
$b = array(
|
||||
'subkey' => array(
|
||||
20 => 'C',
|
||||
0 => 'D',
|
||||
),
|
||||
);
|
||||
|
||||
// Drupal core behavior.
|
||||
$expected = array(
|
||||
'subkey' => array(
|
||||
0 => 'A',
|
||||
1 => 'B',
|
||||
2 => 'C',
|
||||
3 => 'D',
|
||||
),
|
||||
);
|
||||
$actual = NestedArray::mergeDeepArray(array($a, $b));
|
||||
$this->assertSame($expected, $actual, 'drupal_array_merge_deep() ignores numeric key order when merging.');
|
||||
}
|
||||
|
||||
}
|
163
core/tests/Drupal/Tests/Component/Utility/NumberTest.php
Normal file
163
core/tests/Drupal/Tests/Component/Utility/NumberTest.php
Normal file
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\NumberTest.
|
||||
*
|
||||
* @see \Drupal\Component\Utility\Number
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\Number;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests number manipulation utilities.
|
||||
*
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Number
|
||||
*/
|
||||
class NumberTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests Number::validStep() without offset.
|
||||
*
|
||||
* @dataProvider providerTestValidStep
|
||||
* @covers ::validStep
|
||||
*
|
||||
* @param numeric $value
|
||||
* The value argument for Number::validStep().
|
||||
* @param numeric $step
|
||||
* The step argument for Number::validStep().
|
||||
* @param bool $expected
|
||||
* Expected return value from Number::validStep().
|
||||
*/
|
||||
public function testValidStep($value, $step, $expected) {
|
||||
$return = Number::validStep($value, $step);
|
||||
$this->assertEquals($expected, $return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Number::validStep() with offset.
|
||||
*
|
||||
* @dataProvider providerTestValidStepOffset
|
||||
* @covers ::validStep
|
||||
*
|
||||
* @param numeric $value
|
||||
* The value argument for Number::validStep().
|
||||
* @param numeric $step
|
||||
* The step argument for Number::validStep().
|
||||
* @param numeric $offset
|
||||
* The offset argument for Number::validStep().
|
||||
* @param bool $expected
|
||||
* Expected return value from Number::validStep().
|
||||
*/
|
||||
public function testValidStepOffset($value, $step, $offset, $expected) {
|
||||
$return = Number::validStep($value, $step, $offset);
|
||||
$this->assertEquals($expected, $return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testNumberStep().
|
||||
*
|
||||
* @see \Drupal\Tests\Component\Utility\Number::testValidStep
|
||||
*/
|
||||
public static function providerTestValidStep() {
|
||||
return array(
|
||||
// Value and step equal.
|
||||
array(10.3, 10.3, TRUE),
|
||||
|
||||
// Valid integer steps.
|
||||
array(42, 21, TRUE),
|
||||
array(42, 3, TRUE),
|
||||
|
||||
// Valid float steps.
|
||||
array(42, 10.5, TRUE),
|
||||
array(1, 1/3, TRUE),
|
||||
array(-100, 100/7, TRUE),
|
||||
array(1000, -10, TRUE),
|
||||
|
||||
// Valid and very small float steps.
|
||||
array(1000.12345, 1e-10, TRUE),
|
||||
array(3.9999999999999, 1e-13, TRUE),
|
||||
|
||||
// Invalid integer steps.
|
||||
array(100, 30, FALSE),
|
||||
array(-10, 4, FALSE),
|
||||
|
||||
// Invalid float steps.
|
||||
array(6, 5/7, FALSE),
|
||||
array(10.3, 10.25, FALSE),
|
||||
|
||||
// Step mismatches very close to being valid.
|
||||
array(70 + 9e-7, 10 + 9e-7, FALSE),
|
||||
array(1936.5, 3e-8, FALSE),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for \Drupal\Test\Component\Utility\NumberTest::testValidStepOffset().
|
||||
*
|
||||
* @see \Drupal\Test\Component\Utility\NumberTest::testValidStepOffset()
|
||||
*/
|
||||
public static function providerTestValidStepOffset() {
|
||||
return array(
|
||||
// Try obvious fits.
|
||||
array(11.3, 10.3, 1, TRUE),
|
||||
array(100, 10, 50, TRUE),
|
||||
array(-100, 90/7, -10, TRUE),
|
||||
array(2/7 + 5/9, 1/7, 5/9, TRUE),
|
||||
|
||||
// Ensure a small offset is still invalid.
|
||||
array(10.3, 10.3, 0.0001, FALSE),
|
||||
array(1/5, 1/7, 1/11, FALSE),
|
||||
|
||||
// Try negative values and offsets.
|
||||
array(1000, 10, -5, FALSE),
|
||||
array(-10, 4, 0, FALSE),
|
||||
array(-10, 4, -4, FALSE),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the alphadecimal conversion functions.
|
||||
*
|
||||
* @dataProvider providerTestConversions
|
||||
* @covers ::intToAlphadecimal
|
||||
* @covers ::alphadecimalToInt
|
||||
*
|
||||
* @param int $value
|
||||
* The integer value.
|
||||
* @param string $expected
|
||||
* The expected alphadecimal value.
|
||||
*/
|
||||
public function testConversions($value, $expected) {
|
||||
$this->assertSame(Number::intToAlphadecimal($value), $expected);
|
||||
$this->assertSame($value, Number::alphadecimalToInt($expected));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testConversions().
|
||||
*
|
||||
* @see testConversions()
|
||||
*
|
||||
* @return array
|
||||
* An array containing:
|
||||
* - The integer value.
|
||||
* - The alphadecimal value.
|
||||
*/
|
||||
public function providerTestConversions() {
|
||||
return array(
|
||||
array(0, '00'),
|
||||
array(1, '01'),
|
||||
array(10, '0a'),
|
||||
array(20, '0k'),
|
||||
array(35, '0z'),
|
||||
array(36, '110'),
|
||||
array(100, '12s'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
172
core/tests/Drupal/Tests/Component/Utility/RandomTest.php
Normal file
172
core/tests/Drupal/Tests/Component/Utility/RandomTest.php
Normal file
|
@ -0,0 +1,172 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\RandomTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\Random;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests random data generation.
|
||||
*
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Random
|
||||
*/
|
||||
class RandomTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The first random string passed to the test callback.
|
||||
*
|
||||
* @see \Drupal\Tests\Component\Utility\RandomTest::_RandomStringValidate()
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $firstStringGenerated = '';
|
||||
|
||||
/**
|
||||
* Tests unique random string generation.
|
||||
*
|
||||
* @covers ::string
|
||||
*/
|
||||
public function testRandomStringUniqueness() {
|
||||
$strings = array();
|
||||
$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)));
|
||||
$strings[$str] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests unique random name generation.
|
||||
*
|
||||
* @covers ::name
|
||||
*/
|
||||
public function testRandomNamesUniqueness() {
|
||||
$names = array();
|
||||
$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)));
|
||||
$names[$str] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests infinite loop prevention whilst generating random names.
|
||||
*
|
||||
* @covers ::name
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testRandomNameException() {
|
||||
// There are fewer than 100 possibilities so an exception should occur to
|
||||
// prevent infinite loops.
|
||||
$random = new Random();
|
||||
for ($i = 0; $i <= 100; $i++) {
|
||||
$str = $random->name(1, TRUE);
|
||||
$names[$str] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests infinite loop prevention whilst generating random strings.
|
||||
*
|
||||
* @covers ::string
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testRandomStringException() {
|
||||
// There are fewer than 100 possibilities so an exception should occur to
|
||||
// prevent infinite loops.
|
||||
$random = new Random();
|
||||
for ($i = 0; $i <= 100; $i++) {
|
||||
$str = $random->string(1, TRUE);
|
||||
$names[$str] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests random name generation if uniqueness is not enforced.
|
||||
*
|
||||
* @covers ::name
|
||||
*/
|
||||
public function testRandomNameNonUnique() {
|
||||
// There are fewer than 100 possibilities if we were forcing uniqueness so
|
||||
// exception would occur.
|
||||
$random = new Random();
|
||||
for ($i = 0; $i <= 100; $i++) {
|
||||
$random->name(1);
|
||||
}
|
||||
$this->assertTrue(TRUE, 'No exception thrown when uniqueness is not enforced.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests random string if uniqueness is not enforced.
|
||||
*
|
||||
* @covers ::string
|
||||
*/
|
||||
public function testRandomStringNonUnique() {
|
||||
// There are fewer than 100 possibilities if we were forcing uniqueness so
|
||||
// exception would occur.
|
||||
$random = new Random();
|
||||
for ($i = 0; $i <= 100; $i++) {
|
||||
$random->string(1);
|
||||
}
|
||||
$this->assertTrue(TRUE, 'No exception thrown when uniqueness is not enforced.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests random object generation to ensure the expected number of properties.
|
||||
*
|
||||
* @covers ::object
|
||||
*/
|
||||
public function testRandomObject() {
|
||||
// For values of 0 and 1 \Drupal\Component\Utility\Random::object() will
|
||||
// have different execution paths.
|
||||
$random = new Random();
|
||||
for ($i = 0; $i <= 1; $i++) {
|
||||
$obj = $random->object($i);
|
||||
$this->assertEquals($i, count(get_object_vars($obj)), 'Generated random object has expected number of properties');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests random string validation callbacks.
|
||||
*
|
||||
* @covers ::string
|
||||
*/
|
||||
public function testRandomStringValidator() {
|
||||
$random = new Random();
|
||||
$this->firstStringGenerated = '';
|
||||
$str = $random->string(1, TRUE, array($this, '_RandomStringValidate'));
|
||||
$this->assertNotEquals($this->firstStringGenerated, $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for random string validation.
|
||||
*
|
||||
* @see \Drupal\Component\Utility\Random::name()
|
||||
* @see \Drupal\Tests\Component\Utility\RandomTest::testRandomStringValidator()
|
||||
*
|
||||
* @param string $string
|
||||
* The random string to validate.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the random string is valid, FALSE if not.
|
||||
*/
|
||||
public function _RandomStringValidate($string) {
|
||||
// Return FALSE for the first generated string and any string that is the
|
||||
// same, as the test expects a different string to be returned.
|
||||
if (empty($this->firstStringGenerated) || $string == $this->firstStringGenerated) {
|
||||
$this->firstStringGenerated = $string;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
286
core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php
Normal file
286
core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php
Normal file
|
@ -0,0 +1,286 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\SafeMarkupTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests marking strings as safe.
|
||||
*
|
||||
* @group Utility
|
||||
* @coversDefaultClass \Drupal\Component\Utility\SafeMarkup
|
||||
*/
|
||||
class SafeMarkupTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests SafeMarkup::set() and SafeMarkup::isSafe().
|
||||
*
|
||||
* @dataProvider providerSet
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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');
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SafeMarkup::set() and SafeMarkup::isSafe() with different providers.
|
||||
*
|
||||
* @covers ::isSafe
|
||||
*/
|
||||
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"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SafeMarkup::isSafe() with different objects.
|
||||
*
|
||||
* @covers ::isSafe
|
||||
*/
|
||||
public function testIsSafe() {
|
||||
$safe_string = $this->getMock('\Drupal\Component\Utility\SafeStringInterface');
|
||||
$this->assertTrue(SafeMarkup::isSafe($safe_string));
|
||||
$string_object = new SafeMarkupTestString('test');
|
||||
$this->assertFalse(SafeMarkup::isSafe($string_object));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SafeMarkup::setMultiple().
|
||||
*
|
||||
* @covers ::setMultiple
|
||||
*/
|
||||
public function testSetMultiple() {
|
||||
$texts = array(
|
||||
'multistring0' => array('html' => TRUE),
|
||||
'multistring1' => array('all' => TRUE),
|
||||
);
|
||||
SafeMarkup::setMultiple($texts);
|
||||
foreach ($texts as $string => $providers) {
|
||||
$this->assertTrue(SafeMarkup::isSafe($string), 'The value has been marked as safe for html');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SafeMarkup::setMultiple().
|
||||
*
|
||||
* Only TRUE may be passed in as the value.
|
||||
*
|
||||
* @covers ::setMultiple
|
||||
*
|
||||
* @expectedException \UnexpectedValueException
|
||||
*/
|
||||
public function testInvalidSetMultiple() {
|
||||
$texts = array(
|
||||
'invalidstring0' => array('html' => 1),
|
||||
);
|
||||
SafeMarkup::setMultiple($texts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SafeMarkup::checkPlain().
|
||||
*
|
||||
* @dataProvider providerCheckPlain
|
||||
* @covers ::checkPlain
|
||||
*
|
||||
* @param string $text
|
||||
* The text to provide to SafeMarkup::checkPlain().
|
||||
* @param string $expected
|
||||
* The expected output from the function.
|
||||
* @param string $message
|
||||
* The message to provide as output for the test.
|
||||
* @param bool $ignorewarnings
|
||||
* Whether or not to ignore PHP 5.3+ invalid multibyte sequence warnings.
|
||||
*/
|
||||
function testCheckPlain($text, $expected, $message, $ignorewarnings = FALSE) {
|
||||
$result = $ignorewarnings ? @SafeMarkup::checkPlain($text) : SafeMarkup::checkPlain($text);
|
||||
$this->assertEquals($expected, $result, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testCheckPlain().
|
||||
*
|
||||
* @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 special characters are escaped.
|
||||
$tests[] = array("<script>", '<script>', 'SafeMarkup::checkPlain() escapes <script>');
|
||||
$tests[] = array('<>&"\'', '<>&"'', 'SafeMarkup::checkPlain() escapes reserved HTML characters.');
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests string formatting with SafeMarkup::format().
|
||||
*
|
||||
* @dataProvider providerFormat
|
||||
* @covers ::format
|
||||
*
|
||||
* @param string $string
|
||||
* The string to run through SafeMarkup::format().
|
||||
* @param string $args
|
||||
* The arguments to pass into SafeMarkup::format().
|
||||
* @param string $expected
|
||||
* The expected result from calling the function.
|
||||
* @param string $message
|
||||
* The message to display as output to the test.
|
||||
* @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) {
|
||||
$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.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testFormat().
|
||||
*
|
||||
* @see testFormat()
|
||||
*/
|
||||
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('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('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));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SafeMarkupTestString {
|
||||
|
||||
protected $string;
|
||||
|
||||
public function __construct($string) {
|
||||
$this->string = $string;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->string;
|
||||
}
|
||||
|
||||
}
|
328
core/tests/Drupal/Tests/Component/Utility/SortArrayTest.php
Normal file
328
core/tests/Drupal/Tests/Component/Utility/SortArrayTest.php
Normal file
|
@ -0,0 +1,328 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\SortArrayTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Component\Utility\SortArray;
|
||||
|
||||
/**
|
||||
* Tests the SortArray component.
|
||||
*
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\SortArray
|
||||
*/
|
||||
class SortArrayTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests SortArray::sortByWeightElement() input against expected output.
|
||||
*
|
||||
* @dataProvider providerSortByWeightElement
|
||||
* @covers ::sortByWeightElement
|
||||
* @covers ::sortByKeyInt
|
||||
*
|
||||
* @param array $a
|
||||
* The first input array for the SortArray::sortByWeightElement() method.
|
||||
* @param array $b
|
||||
* The second input array for the SortArray::sortByWeightElement().
|
||||
* @param integer $expected
|
||||
* The expected output from calling the method.
|
||||
*/
|
||||
public function testSortByWeightElement($a, $b, $expected) {
|
||||
$result = SortArray::sortByWeightElement($a, $b);
|
||||
$this->assertBothNegativePositiveOrZero($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for SortArray::sortByWeightElement().
|
||||
*
|
||||
* @return array
|
||||
* An array of tests, matching the parameter inputs for
|
||||
* testSortByWeightElement.
|
||||
*
|
||||
* @see \Drupal\Tests\Component\Utility\SortArrayTest::testSortByWeightElement()
|
||||
*/
|
||||
public function providerSortByWeightElement() {
|
||||
$tests = array();
|
||||
|
||||
// Weights set and equal.
|
||||
$tests[] = array(
|
||||
array('weight' => 1),
|
||||
array('weight' => 1),
|
||||
0
|
||||
);
|
||||
|
||||
// Weights set and $a is less (lighter) than $b.
|
||||
$tests[] = array(
|
||||
array('weight' => 1),
|
||||
array('weight' => 2),
|
||||
-1
|
||||
);
|
||||
|
||||
// Weights set and $a is greater (heavier) than $b.
|
||||
$tests[] = array(
|
||||
array('weight' => 2),
|
||||
array('weight' => 1),
|
||||
1
|
||||
);
|
||||
|
||||
// Weights not set.
|
||||
$tests[] = array(
|
||||
array(),
|
||||
array(),
|
||||
0
|
||||
);
|
||||
|
||||
// Weights for $b not set.
|
||||
$tests[] = array(
|
||||
array('weight' => 1),
|
||||
array(),
|
||||
1
|
||||
);
|
||||
|
||||
// Weights for $a not set.
|
||||
$tests[] = array(
|
||||
array(),
|
||||
array('weight' => 1),
|
||||
-1
|
||||
);
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SortArray::sortByWeightProperty() input against expected output.
|
||||
*
|
||||
* @dataProvider providerSortByWeightProperty
|
||||
* @covers ::sortByWeightProperty
|
||||
* @covers ::sortByKeyInt
|
||||
*
|
||||
* @param array $a
|
||||
* The first input array for the SortArray::sortByWeightProperty() method.
|
||||
* @param array $b
|
||||
* The second input array for the SortArray::sortByWeightProperty().
|
||||
* @param integer $expected
|
||||
* The expected output from calling the method.
|
||||
*/
|
||||
public function testSortByWeightProperty($a, $b, $expected) {
|
||||
$result = SortArray::sortByWeightProperty($a, $b);
|
||||
$this->assertBothNegativePositiveOrZero($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for SortArray::sortByWeightProperty().
|
||||
*
|
||||
* @return array
|
||||
* An array of tests, matching the parameter inputs for
|
||||
* testSortByWeightProperty.
|
||||
*
|
||||
* @see \Drupal\Tests\Component\Utility\SortArrayTest::testSortByWeightProperty()
|
||||
*/
|
||||
public function providerSortByWeightProperty() {
|
||||
$tests = array();
|
||||
|
||||
// Weights set and equal.
|
||||
$tests[] = array(
|
||||
array('#weight' => 1),
|
||||
array('#weight' => 1),
|
||||
0
|
||||
);
|
||||
|
||||
// Weights set and $a is less (lighter) than $b.
|
||||
$tests[] = array(
|
||||
array('#weight' => 1),
|
||||
array('#weight' => 2),
|
||||
-1
|
||||
);
|
||||
|
||||
// Weights set and $a is greater (heavier) than $b.
|
||||
$tests[] = array(
|
||||
array('#weight' => 2),
|
||||
array('#weight' => 1),
|
||||
1
|
||||
);
|
||||
|
||||
// Weights not set.
|
||||
$tests[] = array(
|
||||
array(),
|
||||
array(),
|
||||
0
|
||||
);
|
||||
|
||||
// Weights for $b not set.
|
||||
$tests[] = array(
|
||||
array('#weight' => 1),
|
||||
array(),
|
||||
1
|
||||
);
|
||||
|
||||
// Weights for $a not set.
|
||||
$tests[] = array(
|
||||
array(),
|
||||
array('#weight' => 1),
|
||||
-1
|
||||
);
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SortArray::sortByTitleElement() input against expected output.
|
||||
*
|
||||
* @dataProvider providerSortByTitleElement
|
||||
* @covers ::sortByTitleElement
|
||||
* @covers ::sortByKeyString
|
||||
*
|
||||
* @param array $a
|
||||
* The first input item for comparison.
|
||||
* @param array $b
|
||||
* The second item for comparison.
|
||||
* @param integer $expected
|
||||
* The expected output from calling the method.
|
||||
*/
|
||||
public function testSortByTitleElement($a, $b, $expected) {
|
||||
$result = SortArray::sortByTitleElement($a, $b);
|
||||
$this->assertBothNegativePositiveOrZero($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for SortArray::sortByTitleElement().
|
||||
*
|
||||
* @return array
|
||||
* An array of tests, matching the parameter inputs for
|
||||
* testSortByTitleElement.
|
||||
*
|
||||
* @see \Drupal\Tests\Component\Utility\SortArrayTest::testSortByTitleElement()
|
||||
*/
|
||||
public function providerSortByTitleElement() {
|
||||
$tests = array();
|
||||
|
||||
// Titles set and equal.
|
||||
$tests[] = array(
|
||||
array('title' => 'test'),
|
||||
array('title' => 'test'),
|
||||
0
|
||||
);
|
||||
|
||||
// Title $a not set.
|
||||
$tests[] = array(
|
||||
array(),
|
||||
array('title' => 'test'),
|
||||
-4
|
||||
);
|
||||
|
||||
// Title $b not set.
|
||||
$tests[] = array(
|
||||
array('title' => 'test'),
|
||||
array(),
|
||||
4
|
||||
);
|
||||
|
||||
// Titles set but not equal.
|
||||
$tests[] = array(
|
||||
array('title' => 'test'),
|
||||
array('title' => 'testing'),
|
||||
-1
|
||||
);
|
||||
|
||||
// Titles set but not equal.
|
||||
$tests[] = array(
|
||||
array('title' => 'testing'),
|
||||
array('title' => 'test'),
|
||||
1
|
||||
);
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SortArray::sortByTitleProperty() input against expected output.
|
||||
*
|
||||
* @dataProvider providerSortByTitleProperty
|
||||
* @covers ::sortByTitleProperty
|
||||
* @covers ::sortByKeyString
|
||||
*
|
||||
* @param array $a
|
||||
* The first input item for comparison.
|
||||
* @param array $b
|
||||
* The second item for comparison.
|
||||
* @param integer $expected
|
||||
* The expected output from calling the method.
|
||||
*/
|
||||
public function testSortByTitleProperty($a, $b, $expected) {
|
||||
$result = SortArray::sortByTitleProperty($a, $b);
|
||||
$this->assertBothNegativePositiveOrZero($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for SortArray::sortByTitleProperty().
|
||||
*
|
||||
* @return array
|
||||
* An array of tests, matching the parameter inputs for
|
||||
* testSortByTitleProperty.
|
||||
*
|
||||
* @see \Drupal\Tests\Component\Utility\SortArrayTest::testSortByTitleProperty()
|
||||
*/
|
||||
public function providerSortByTitleProperty() {
|
||||
$tests = array();
|
||||
|
||||
// Titles set and equal.
|
||||
$tests[] = array(
|
||||
array('#title' => 'test'),
|
||||
array('#title' => 'test'),
|
||||
0
|
||||
);
|
||||
|
||||
// Title $a not set.
|
||||
$tests[] = array(
|
||||
array(),
|
||||
array('#title' => 'test'),
|
||||
-4
|
||||
);
|
||||
|
||||
// Title $b not set.
|
||||
$tests[] = array(
|
||||
array('#title' => 'test'),
|
||||
array(),
|
||||
4
|
||||
);
|
||||
|
||||
// Titles set but not equal.
|
||||
$tests[] = array(
|
||||
array('#title' => 'test'),
|
||||
array('#title' => 'testing'),
|
||||
-1
|
||||
);
|
||||
|
||||
// Titles set but not equal.
|
||||
$tests[] = array(
|
||||
array('#title' => 'testing'),
|
||||
array('#title' => 'test'),
|
||||
1
|
||||
);
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that numbers are either both negative, both positive or both zero.
|
||||
*
|
||||
* The exact values returned by comparison functions differ between PHP
|
||||
* versions and are considered an "implementation detail".
|
||||
*
|
||||
* @param int $expected
|
||||
* Expected comparison function return value.
|
||||
* @param int $result
|
||||
* Actual comparison function return value.
|
||||
*/
|
||||
protected function assertBothNegativePositiveOrZero($expected, $result) {
|
||||
$this->assertTrue(is_numeric($expected) && is_numeric($result), 'Parameters are numeric.');
|
||||
$this->assertTrue(($expected < 0 && $result < 0) || ($expected > 0 && $result > 0) || ($expected === 0 && $result === 0), 'Numbers are either both negative, both positive or both zero.');
|
||||
}
|
||||
|
||||
}
|
39
core/tests/Drupal/Tests/Component/Utility/TextWrapper.php
Normal file
39
core/tests/Drupal/Tests/Component/Utility/TextWrapper.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\TextWrapper.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
/**
|
||||
* Used by SafeMarkupTest to test that a class with a __toString() method works.
|
||||
*/
|
||||
class TextWrapper {
|
||||
|
||||
/**
|
||||
* The text value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $text = '';
|
||||
|
||||
/**
|
||||
* Constructs a \Drupal\Tests\Component\Utility\TextWrapper
|
||||
*
|
||||
* @param string $text
|
||||
*/
|
||||
public function __construct($text) {
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString() {
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
}
|
73
core/tests/Drupal/Tests/Component/Utility/TimerTest.php
Normal file
73
core/tests/Drupal/Tests/Component/Utility/TimerTest.php
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\TimerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Component\Utility\Timer;
|
||||
|
||||
/**
|
||||
* Tests the Timer system.
|
||||
*
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Timer
|
||||
*/
|
||||
class TimerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests Timer::read() time accumulation accuracy across multiple restarts.
|
||||
*
|
||||
* @covers ::start
|
||||
* @covers ::stop
|
||||
* @covers ::read
|
||||
*/
|
||||
public function testTimer() {
|
||||
Timer::start('test');
|
||||
usleep(5000);
|
||||
$value = Timer::read('test');
|
||||
usleep(5000);
|
||||
$value2 = Timer::read('test');
|
||||
usleep(5000);
|
||||
$value3 = Timer::read('test');
|
||||
usleep(5000);
|
||||
$value4 = Timer::read('test');
|
||||
|
||||
// Although we sleep for 5 milliseconds, we should test that at least 4 ms
|
||||
// have past because usleep() is not reliable on Windows. See
|
||||
// http://php.net/manual/en/function.usleep.php for more information. The
|
||||
// purpose of the test to validate that the Timer class can measure elapsed
|
||||
// time not the granularity of usleep() on a particular OS.
|
||||
$this->assertGreaterThanOrEqual(4, $value, 'Timer failed to measure at least 4 milliseconds of sleeping while running.');
|
||||
|
||||
$this->assertGreaterThanOrEqual($value + 4, $value2, 'Timer failed to measure at least 8 milliseconds of sleeping while running.');
|
||||
|
||||
$this->assertGreaterThanOrEqual($value2 + 4, $value3, 'Timer failed to measure at least 12 milliseconds of sleeping while running.');
|
||||
|
||||
$this->assertGreaterThanOrEqual($value3 + 4, $value4, 'Timer failed to measure at least 16 milliseconds of sleeping while running.');
|
||||
|
||||
// Stop the timer.
|
||||
$value5 = Timer::stop('test');
|
||||
$this->assertGreaterThanOrEqual($value4, $value5['time'], 'Timer measured after stopping was not greater than last measurement.');
|
||||
|
||||
// Read again.
|
||||
$value6 = Timer::read('test');
|
||||
$this->assertEquals($value5['time'], $value6, 'Timer measured after stopping was not equal to the stopped time.');
|
||||
|
||||
// Restart.
|
||||
Timer::start('test');
|
||||
usleep(5000);
|
||||
$value7 = Timer::read('test');
|
||||
$this->assertGreaterThanOrEqual($value6 + 4, $value7, 'Timer failed to measure at least 16 milliseconds of sleeping while running.');
|
||||
|
||||
// Stop again.
|
||||
$value8 = Timer::stop('test');
|
||||
$value9 = Timer::read('test');
|
||||
$this->assertEquals($value8['time'], $value9, 'Timer measured after stopping not equal to stop time.');
|
||||
}
|
||||
|
||||
}
|
532
core/tests/Drupal/Tests/Component/Utility/UnicodeTest.php
Normal file
532
core/tests/Drupal/Tests/Component/Utility/UnicodeTest.php
Normal file
|
@ -0,0 +1,532 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\UnicodeTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
|
||||
/**
|
||||
* Test unicode handling features implemented in Unicode component.
|
||||
*
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Unicode
|
||||
*/
|
||||
class UnicodeTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @covers ::check
|
||||
*/
|
||||
public function setUp() {
|
||||
// Initialize unicode component.
|
||||
Unicode::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getting and settings the multibyte environment status.
|
||||
*
|
||||
* @dataProvider providerTestStatus
|
||||
* @covers ::getStatus
|
||||
* @covers ::setStatus
|
||||
*/
|
||||
public function testStatus($value, $expected, $invalid = FALSE) {
|
||||
if ($invalid) {
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
}
|
||||
Unicode::setStatus($value);
|
||||
$this->assertEquals($expected, Unicode::getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testStatus().
|
||||
*
|
||||
* @see testStatus()
|
||||
*
|
||||
* @return array
|
||||
* An array containing:
|
||||
* - The status value to set.
|
||||
* - The status value to expect after setting the new value.
|
||||
* - (optional) Boolean indicating invalid status. Defaults to FALSE.
|
||||
*/
|
||||
public function providerTestStatus() {
|
||||
return array(
|
||||
array(Unicode::STATUS_SINGLEBYTE, Unicode::STATUS_SINGLEBYTE),
|
||||
array(rand(10, 100), Unicode::STATUS_SINGLEBYTE, TRUE),
|
||||
array(rand(10, 100), Unicode::STATUS_SINGLEBYTE, TRUE),
|
||||
array(Unicode::STATUS_MULTIBYTE, Unicode::STATUS_MULTIBYTE),
|
||||
array(rand(10, 100), Unicode::STATUS_MULTIBYTE, TRUE),
|
||||
array(Unicode::STATUS_ERROR, Unicode::STATUS_ERROR),
|
||||
array(Unicode::STATUS_MULTIBYTE, Unicode::STATUS_MULTIBYTE),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multibyte encoding and decoding.
|
||||
*
|
||||
* @dataProvider providerTestMimeHeader
|
||||
* @covers ::mimeHeaderEncode
|
||||
* @covers ::mimeHeaderDecode
|
||||
*/
|
||||
public function testMimeHeader($value, $encoded) {
|
||||
$this->assertEquals($encoded, Unicode::mimeHeaderEncode($value));
|
||||
$this->assertEquals($value, Unicode::mimeHeaderDecode($encoded));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testMimeHeader().
|
||||
*
|
||||
* @see testMimeHeader()
|
||||
*
|
||||
* @return array
|
||||
* An array containing a string and its encoded value.
|
||||
*/
|
||||
public function providerTestMimeHeader() {
|
||||
return array(
|
||||
array('tést.txt', '=?UTF-8?B?dMOpc3QudHh0?='),
|
||||
// Simple ASCII characters.
|
||||
array('ASCII', 'ASCII'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multibyte strtolower.
|
||||
*
|
||||
* @dataProvider providerStrtolower
|
||||
* @covers ::strtolower
|
||||
* @covers ::caseFlip
|
||||
*/
|
||||
public function testStrtolower($text, $expected, $multibyte = FALSE) {
|
||||
$status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE;
|
||||
Unicode::setStatus($status);
|
||||
$this->assertEquals($expected, Unicode::strtolower($text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testStrtolower().
|
||||
*
|
||||
* @see testStrtolower()
|
||||
*
|
||||
* @return array
|
||||
* An array containing a string, its lowercase version and whether it should
|
||||
* be processed as multibyte.
|
||||
*/
|
||||
public function providerStrtolower() {
|
||||
$cases = array(
|
||||
array('tHe QUIcK bRoWn', 'the quick brown'),
|
||||
array('FrançAIS is ÜBER-åwesome', 'français is über-åwesome'),
|
||||
);
|
||||
foreach ($cases as $case) {
|
||||
// Test the same string both in multibyte and singlebyte conditions.
|
||||
array_push($case, TRUE);
|
||||
$cases[] = $case;
|
||||
}
|
||||
// Add a multibyte string.
|
||||
$cases[] = array('ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', 'αβγδεζηθικλμνξοσὠ', TRUE);
|
||||
return $cases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multibyte strtoupper.
|
||||
*
|
||||
* @dataProvider providerStrtoupper
|
||||
* @covers ::strtoupper
|
||||
* @covers ::caseFlip
|
||||
*/
|
||||
public function testStrtoupper($text, $expected, $multibyte = FALSE) {
|
||||
$status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE;
|
||||
Unicode::setStatus($status);
|
||||
$this->assertEquals($expected, Unicode::strtoupper($text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testStrtoupper().
|
||||
*
|
||||
* @see testStrtoupper()
|
||||
*
|
||||
* @return array
|
||||
* An array containing a string, its uppercase version and whether it should
|
||||
* be processed as multibyte.
|
||||
*/
|
||||
public function providerStrtoupper() {
|
||||
$cases = array(
|
||||
array('tHe QUIcK bRoWn', 'THE QUICK BROWN'),
|
||||
array('FrançAIS is ÜBER-åwesome', 'FRANÇAIS IS ÜBER-ÅWESOME'),
|
||||
);
|
||||
foreach ($cases as $case) {
|
||||
// Test the same string both in multibyte and singlebyte conditions.
|
||||
array_push($case, TRUE);
|
||||
$cases[] = $case;
|
||||
}
|
||||
// Add a multibyte string.
|
||||
$cases[] = array('αβγδεζηθικλμνξοσὠ', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', TRUE);
|
||||
return $cases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multibyte ucfirst.
|
||||
*
|
||||
* @dataProvider providerUcfirst
|
||||
* @covers ::ucfirst
|
||||
*/
|
||||
public function testUcfirst($text, $expected) {
|
||||
$this->assertEquals($expected, Unicode::ucfirst($text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testUcfirst().
|
||||
*
|
||||
* @see testUcfirst()
|
||||
*
|
||||
* @return array
|
||||
* An array containing a string and its uppercase first version.
|
||||
*/
|
||||
public function providerUcfirst() {
|
||||
return array(
|
||||
array('tHe QUIcK bRoWn', 'THe QUIcK bRoWn'),
|
||||
array('françAIS', 'FrançAIS'),
|
||||
array('über', 'Über'),
|
||||
array('åwesome', 'Åwesome'),
|
||||
// A multibyte string.
|
||||
array('σion', 'Σion'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multibyte lcfirst.
|
||||
*
|
||||
* @dataProvider providerLcfirst
|
||||
* @covers ::lcfirst
|
||||
*/
|
||||
public function testLcfirst($text, $expected, $multibyte = FALSE) {
|
||||
$status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE;
|
||||
Unicode::setStatus($status);
|
||||
$this->assertEquals($expected, Unicode::lcfirst($text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testLcfirst().
|
||||
*
|
||||
* @see testLcfirst()
|
||||
*
|
||||
* @return array
|
||||
* An array containing a string, its lowercase version and whether it should
|
||||
* be processed as multibyte.
|
||||
*/
|
||||
public function providerLcfirst() {
|
||||
return array(
|
||||
array('tHe QUIcK bRoWn', 'tHe QUIcK bRoWn'),
|
||||
array('FrançAIS is ÜBER-åwesome', 'françAIS is ÜBER-åwesome'),
|
||||
array('Über', 'über'),
|
||||
array('Åwesome', 'åwesome'),
|
||||
// Add a multibyte string.
|
||||
array('ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', 'αΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', TRUE),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multibyte ucwords.
|
||||
*
|
||||
* @dataProvider providerUcwords
|
||||
* @covers ::ucwords
|
||||
*/
|
||||
public function testUcwords($text, $expected, $multibyte = FALSE) {
|
||||
$status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE;
|
||||
Unicode::setStatus($status);
|
||||
$this->assertEquals($expected, Unicode::ucwords($text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testUcwords().
|
||||
*
|
||||
* @see testUcwords()
|
||||
*
|
||||
* @return array
|
||||
* An array containing a string, its capitalized version and whether it should
|
||||
* be processed as multibyte.
|
||||
*/
|
||||
public function providerUcwords() {
|
||||
return array(
|
||||
array('tHe QUIcK bRoWn', 'THe QUIcK BRoWn'),
|
||||
array('françAIS', 'FrançAIS'),
|
||||
array('über', 'Über'),
|
||||
array('åwesome', 'Åwesome'),
|
||||
// Make sure we don't mangle extra spaces.
|
||||
array('frànçAIS is über-åwesome', 'FrànçAIS Is Über-Åwesome'),
|
||||
// Add a multibyte string.
|
||||
array('σion', 'Σion', TRUE),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multibyte strlen.
|
||||
*
|
||||
* @dataProvider providerStrlen
|
||||
* @covers ::strlen
|
||||
*/
|
||||
public function testStrlen($text, $expected) {
|
||||
// Run through multibyte code path.
|
||||
Unicode::setStatus(Unicode::STATUS_MULTIBYTE);
|
||||
$this->assertEquals($expected, Unicode::strlen($text));
|
||||
// Run through singlebyte code path.
|
||||
Unicode::setStatus(Unicode::STATUS_SINGLEBYTE);
|
||||
$this->assertEquals($expected, Unicode::strlen($text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testStrlen().
|
||||
*
|
||||
* @see testStrlen()
|
||||
*
|
||||
* @return array
|
||||
* An array containing a string and its length.
|
||||
*/
|
||||
public function providerStrlen() {
|
||||
return array(
|
||||
array('tHe QUIcK bRoWn', 15),
|
||||
array('ÜBER-åwesome', 12),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multibyte substr.
|
||||
*
|
||||
* @dataProvider providerSubstr
|
||||
* @covers ::substr
|
||||
*/
|
||||
public function testSubstr($text, $start, $length, $expected) {
|
||||
// Run through multibyte code path.
|
||||
Unicode::setStatus(Unicode::STATUS_MULTIBYTE);
|
||||
$this->assertEquals($expected, Unicode::substr($text, $start, $length));
|
||||
// Run through singlebyte code path.
|
||||
Unicode::setStatus(Unicode::STATUS_SINGLEBYTE);
|
||||
$this->assertEquals($expected, Unicode::substr($text, $start, $length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testSubstr().
|
||||
*
|
||||
* @see testSubstr()
|
||||
*
|
||||
* @return array
|
||||
* An array containing:
|
||||
* - The string to test.
|
||||
* - The start number to be processed by substr.
|
||||
* - The length number to be processed by substr.
|
||||
* - The expected string result.
|
||||
*/
|
||||
public function providerSubstr() {
|
||||
return array(
|
||||
array('frànçAIS is über-åwesome', 0, NULL, 'frànçAIS is über-åwesome'),
|
||||
array('frànçAIS is über-åwesome', 0, 0, ''),
|
||||
array('frànçAIS is über-åwesome', 0, 1, 'f'),
|
||||
array('frànçAIS is über-åwesome', 0, 8, 'frànçAIS'),
|
||||
array('frànçAIS is über-åwesome', 0, 23, 'frànçAIS is über-åwesom'),
|
||||
array('frànçAIS is über-åwesome', 0, 24, 'frànçAIS is über-åwesome'),
|
||||
array('frànçAIS is über-åwesome', 0, 25, 'frànçAIS is über-åwesome'),
|
||||
array('frànçAIS is über-åwesome', 0, 100, 'frànçAIS is über-åwesome'),
|
||||
array('frànçAIS is über-åwesome', 4, 4, 'çAIS'),
|
||||
array('frànçAIS is über-åwesome', 1, 0, ''),
|
||||
array('frànçAIS is über-åwesome', 100, 0, ''),
|
||||
array('frànçAIS is über-åwesome', -4, 2, 'so'),
|
||||
array('frànçAIS is über-åwesome', -4, 3, 'som'),
|
||||
array('frànçAIS is über-åwesome', -4, 4, 'some'),
|
||||
array('frànçAIS is über-åwesome', -4, 5, 'some'),
|
||||
array('frànçAIS is über-åwesome', -7, 10, 'åwesome'),
|
||||
array('frànçAIS is über-åwesome', 5, -10, 'AIS is üb'),
|
||||
array('frànçAIS is über-åwesome', 0, -10, 'frànçAIS is üb'),
|
||||
array('frànçAIS is über-åwesome', 0, -1, 'frànçAIS is über-åwesom'),
|
||||
array('frànçAIS is über-åwesome', -7, -2, 'åweso'),
|
||||
array('frànçAIS is über-åwesome', -7, -6, 'å'),
|
||||
array('frànçAIS is über-åwesome', -7, -7, ''),
|
||||
array('frànçAIS is über-åwesome', -7, -8, ''),
|
||||
array('...', 0, 2, '..'),
|
||||
array('以呂波耳・ほへとち。リヌルヲ。', 1, 3, '呂波耳'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multibyte truncate.
|
||||
*
|
||||
* @dataProvider providerTruncate
|
||||
* @covers ::truncate
|
||||
*/
|
||||
public function testTruncate($text, $max_length, $expected, $wordsafe = FALSE, $add_ellipsis = FALSE) {
|
||||
$this->assertEquals($expected, Unicode::truncate($text, $max_length, $wordsafe, $add_ellipsis));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testTruncate().
|
||||
*
|
||||
* @see testTruncate()
|
||||
*
|
||||
* @return array
|
||||
* An array containing:
|
||||
* - The string to test.
|
||||
* - The max length to truncate this string to.
|
||||
* - The expected string result.
|
||||
* - (optional) Boolean for the $wordsafe flag. Defaults to FALSE.
|
||||
* - (optional) Boolean for the $add_ellipsis flag. Defaults to FALSE.
|
||||
*/
|
||||
public function providerTruncate() {
|
||||
return array(
|
||||
array('frànçAIS is über-åwesome', 24, 'frànçAIS is über-åwesome'),
|
||||
array('frànçAIS is über-åwesome', 23, 'frànçAIS is über-åwesom'),
|
||||
array('frànçAIS is über-åwesome', 17, 'frànçAIS is über-'),
|
||||
array('以呂波耳・ほへとち。リヌルヲ。', 6, '以呂波耳・ほ'),
|
||||
array('frànçAIS is über-åwesome', 24, 'frànçAIS is über-åwesome', FALSE, TRUE),
|
||||
array('frànçAIS is über-åwesome', 23, 'frànçAIS is über-åweso…', FALSE, TRUE),
|
||||
array('frànçAIS is über-åwesome', 17, 'frànçAIS is über…', FALSE, TRUE),
|
||||
array('123', 1, '…', TRUE, TRUE),
|
||||
array('123', 2, '1…', TRUE, TRUE),
|
||||
array('123', 3, '123', TRUE, TRUE),
|
||||
array('1234', 3, '12…', TRUE, TRUE),
|
||||
array('1234567890', 10, '1234567890', TRUE, TRUE),
|
||||
array('12345678901', 10, '123456789…', TRUE, TRUE),
|
||||
array('12345678901', 11, '12345678901', TRUE, TRUE),
|
||||
array('123456789012', 11, '1234567890…', TRUE, TRUE),
|
||||
array('12345 7890', 10, '12345 7890', TRUE, TRUE),
|
||||
array('12345 7890', 9, '12345…', TRUE, TRUE),
|
||||
array('123 567 90', 10, '123 567 90', TRUE, TRUE),
|
||||
array('123 567 901', 10, '123 567…', TRUE, TRUE),
|
||||
array('Stop. Hammertime.', 17, 'Stop. Hammertime.', TRUE, TRUE),
|
||||
array('Stop. Hammertime.', 16, 'Stop…', TRUE, TRUE),
|
||||
array('frànçAIS is über-åwesome', 24, 'frànçAIS is über-åwesome', TRUE, TRUE),
|
||||
array('frànçAIS is über-åwesome', 23, 'frànçAIS is über…', TRUE, TRUE),
|
||||
array('frànçAIS is über-åwesome', 17, 'frànçAIS is über…', TRUE, TRUE),
|
||||
array('¿Dónde está el niño?', 20, '¿Dónde está el niño?', TRUE, TRUE),
|
||||
array('¿Dónde está el niño?', 19, '¿Dónde está el…', TRUE, TRUE),
|
||||
array('¿Dónde está el niño?', 13, '¿Dónde está…', TRUE, TRUE),
|
||||
array('¿Dónde está el niño?', 10, '¿Dónde…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 17, 'Help! Help! Help!', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 16, 'Help! Help!…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 15, 'Help! Help!…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 14, 'Help! Help!…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 13, 'Help! Help!…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 12, 'Help! Help!…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 11, 'Help! Help…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 10, 'Help!…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 9, 'Help!…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 8, 'Help!…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 7, 'Help!…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 6, 'Help!…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 5, 'Help…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 4, 'Hel…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 3, 'He…', TRUE, TRUE),
|
||||
array('Help! Help! Help!', 2, 'H…', TRUE, TRUE),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multibyte truncate bytes.
|
||||
*
|
||||
* @dataProvider providerTestTruncateBytes
|
||||
* @covers ::truncateBytes
|
||||
*
|
||||
* @param string $text
|
||||
* The string to truncate.
|
||||
* @param int $max_length
|
||||
* The upper limit on the returned string length.
|
||||
* @param string $expected
|
||||
* The expected return from Unicode::truncateBytes().
|
||||
*/
|
||||
public function testTruncateBytes($text, $max_length, $expected) {
|
||||
$this->assertEquals($expected, Unicode::truncateBytes($text, $max_length), 'The string was not correctly truncated.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testTruncateBytes().
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays, each containing the parameters to
|
||||
* self::testTruncateBytes().
|
||||
*/
|
||||
public function providerTestTruncateBytes() {
|
||||
return array(
|
||||
// String shorter than max length.
|
||||
array('Short string', 42, 'Short string'),
|
||||
// Simple string longer than max length.
|
||||
array('Longer string than previous.', 10, 'Longer str'),
|
||||
// Unicode.
|
||||
array('以呂波耳・ほへとち。リヌルヲ。', 10, '以呂波'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests UTF-8 validation.
|
||||
*
|
||||
* @dataProvider providerTestValidateUtf8
|
||||
* @covers ::validateUtf8
|
||||
*
|
||||
* @param string $text
|
||||
* The text to validate.
|
||||
* @param bool $expected
|
||||
* The expected return value from Unicode::validateUtf8().
|
||||
* @param string $message
|
||||
* The message to display on failure.
|
||||
*/
|
||||
public function testValidateUtf8($text, $expected, $message) {
|
||||
$this->assertEquals($expected, Unicode::validateUtf8($text), $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testValidateUtf8().
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays, each containing the parameters for
|
||||
* self::testValidateUtf8().
|
||||
*
|
||||
* Invalid UTF-8 examples sourced from http://stackoverflow.com/a/11709412/109119.
|
||||
*/
|
||||
public function providerTestValidateUtf8() {
|
||||
return array(
|
||||
// Empty string.
|
||||
array('', TRUE, 'An empty string did not validate.'),
|
||||
// Simple text string.
|
||||
array('Simple text.', TRUE, 'A simple ASCII text string did not validate.'),
|
||||
// Invalid UTF-8, overlong 5 byte encoding.
|
||||
array(chr(0xF8) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80), FALSE, 'Invalid UTF-8 was validated.'),
|
||||
// High code-point without trailing characters.
|
||||
array(chr(0xD0) . chr(0x01), FALSE, 'Invalid UTF-8 was validated.'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests UTF-8 conversion.
|
||||
*
|
||||
* @dataProvider providerTestConvertToUtf8
|
||||
* @covers ::convertToUtf8
|
||||
*
|
||||
* @param string $data
|
||||
* The data to be converted.
|
||||
* @param string $encoding
|
||||
* The encoding the data is in.
|
||||
* @param string|bool $expected
|
||||
* The expected result.
|
||||
*/
|
||||
public function testConvertToUtf8($data, $encoding, $expected) {
|
||||
$this->assertEquals($expected, Unicode::convertToUtf8($data, $encoding));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data to self::testConvertToUtf8().
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays, each containing the parameters to
|
||||
* self::testConvertUtf8(). }
|
||||
*/
|
||||
public function providerTestConvertToUtf8() {
|
||||
return array(
|
||||
array(chr(0x97), 'Windows-1252', '—'),
|
||||
array(chr(0x99), 'Windows-1252', '™'),
|
||||
array(chr(0x80), 'Windows-1252', '€'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
567
core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php
Normal file
567
core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php
Normal file
|
@ -0,0 +1,567 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\UrlHelperTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\UrlHelper;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\UrlHelper
|
||||
*/
|
||||
class UrlHelperTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Provides test data for testBuildQuery().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestBuildQuery() {
|
||||
return array(
|
||||
array(array('a' => ' &#//+%20@۞'), 'a=%20%26%23//%2B%2520%40%DB%9E', 'Value was properly encoded.'),
|
||||
array(array(' &#//+%20@۞' => 'a'), '%20%26%23%2F%2F%2B%2520%40%DB%9E=a', 'Key was properly encoded.'),
|
||||
array(array('a' => '1', 'b' => '2', 'c' => '3'), 'a=1&b=2&c=3', 'Multiple values were properly concatenated.'),
|
||||
array(array('a' => array('b' => '2', 'c' => '3'), 'd' => 'foo'), 'a[b]=2&a[c]=3&d=foo', 'Nested array was properly encoded.'),
|
||||
array(array('foo' => NULL), 'foo', 'Simple parameters are properly added.'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests query building.
|
||||
*
|
||||
* @dataProvider providerTestBuildQuery
|
||||
* @covers ::buildQuery
|
||||
*
|
||||
* @param array $query
|
||||
* The array of query parameters.
|
||||
* @param string $expected
|
||||
* The expected query string.
|
||||
* @param string $message
|
||||
* The assertion message.
|
||||
*/
|
||||
public function testBuildQuery($query, $expected, $message) {
|
||||
$this->assertEquals(UrlHelper::buildQuery($query), $expected, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testValidAbsolute().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestValidAbsoluteData() {
|
||||
$urls = array(
|
||||
'example.com',
|
||||
'www.example.com',
|
||||
'ex-ample.com',
|
||||
'3xampl3.com',
|
||||
'example.com/parenthesis',
|
||||
'example.com/index.html#pagetop',
|
||||
'example.com:8080',
|
||||
'subdomain.example.com',
|
||||
'example.com/index.php/node',
|
||||
'example.com/index.php/node?param=false',
|
||||
'user@www.example.com',
|
||||
'user:pass@www.example.com:8080/login.php?do=login&style=%23#pagetop',
|
||||
'127.0.0.1',
|
||||
'example.org?',
|
||||
'john%20doe:secret:foo@example.org/',
|
||||
'example.org/~,$\'*;',
|
||||
'caf%C3%A9.example.org',
|
||||
'[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html',
|
||||
);
|
||||
|
||||
return $this->dataEnhanceWithScheme($urls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests valid absolute URLs.
|
||||
*
|
||||
* @dataProvider providerTestValidAbsoluteData
|
||||
* @covers ::isValid
|
||||
*
|
||||
* @param string $url
|
||||
* The url to test.
|
||||
* @param string $scheme
|
||||
* The scheme to test.
|
||||
*/
|
||||
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)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for testInvalidAbsolute().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestInvalidAbsolute() {
|
||||
$data = array(
|
||||
'',
|
||||
'ex!ample.com',
|
||||
'ex%ample.com',
|
||||
);
|
||||
return $this->dataEnhanceWithScheme($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests invalid absolute URLs.
|
||||
*
|
||||
* @dataProvider providerTestInvalidAbsolute
|
||||
* @covers ::isValid
|
||||
*
|
||||
* @param string $url
|
||||
* The url to test.
|
||||
* @param string $scheme
|
||||
* The scheme to test.
|
||||
*/
|
||||
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)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for testValidRelative().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestValidRelativeData() {
|
||||
$data = array(
|
||||
'paren(the)sis',
|
||||
'index.html#pagetop',
|
||||
'index.php/node',
|
||||
'index.php/node?param=false',
|
||||
'login.php?do=login&style=%23#pagetop',
|
||||
);
|
||||
|
||||
return $this->dataEnhanceWithPrefix($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests valid relative URLs.
|
||||
*
|
||||
* @dataProvider providerTestValidRelativeData
|
||||
* @covers ::isValid
|
||||
*
|
||||
* @param string $url
|
||||
* The url to test.
|
||||
* @param string $prefix
|
||||
* The prefix to test.
|
||||
*/
|
||||
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)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for testInvalidRelative().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestInvalidRelativeData() {
|
||||
$data = array(
|
||||
'ex^mple',
|
||||
'example<>',
|
||||
'ex%ample',
|
||||
);
|
||||
return $this->dataEnhanceWithPrefix($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests invalid relative URLs.
|
||||
*
|
||||
* @dataProvider providerTestInvalidRelativeData
|
||||
* @covers ::isValid
|
||||
*
|
||||
* @param string $url
|
||||
* The url to test.
|
||||
* @param string $prefix
|
||||
* The prefix to test.
|
||||
*/
|
||||
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)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests query filtering.
|
||||
*
|
||||
* @dataProvider providerTestFilterQueryParameters
|
||||
* @covers ::filterQueryParameters
|
||||
*
|
||||
* @param array $query
|
||||
* The array of query parameters.
|
||||
* @param array $exclude
|
||||
* A list of $query array keys to remove. Use "parent[child]" to exclude
|
||||
* nested items.
|
||||
* @param array $expected
|
||||
* An array containing query parameters.
|
||||
*/
|
||||
public function testFilterQueryParameters($query, $exclude, $expected) {
|
||||
$filtered = UrlHelper::filterQueryParameters($query, $exclude);
|
||||
$this->assertEquals($expected, $filtered, 'The query was not properly filtered.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data to self::testFilterQueryParameters().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function providerTestFilterQueryParameters() {
|
||||
return array(
|
||||
// Test without an exclude filter.
|
||||
array(
|
||||
'query' => array('a' => array('b' => 'c')),
|
||||
'exclude' => array(),
|
||||
'expected' => array('a' => array('b' => 'c')),
|
||||
),
|
||||
// Exclude the 'b' element.
|
||||
array(
|
||||
'query' => array('a' => array('b' => 'c', 'd' => 'e')),
|
||||
'exclude' => array('a[b]'),
|
||||
'expected' => array('a' => array('d' => 'e')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests url parsing.
|
||||
*
|
||||
* @dataProvider providerTestParse
|
||||
* @covers ::parse
|
||||
*
|
||||
* @param string $url
|
||||
* URL to test.
|
||||
* @param array $expected
|
||||
* Associative array with expected parameters.
|
||||
*/
|
||||
public function testParse($url, $expected) {
|
||||
$parsed = UrlHelper::parse($url);
|
||||
$this->assertEquals($expected, $parsed, 'The url was not properly parsed.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testParse().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function providerTestParse() {
|
||||
return array(
|
||||
array(
|
||||
'http://www.example.com/my/path',
|
||||
array(
|
||||
'path' => 'http://www.example.com/my/path',
|
||||
'query' => array(),
|
||||
'fragment' => '',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'http://www.example.com/my/path?destination=home#footer',
|
||||
array(
|
||||
'path' => 'http://www.example.com/my/path',
|
||||
'query' => array(
|
||||
'destination' => 'home',
|
||||
),
|
||||
'fragment' => 'footer',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'http://',
|
||||
array(
|
||||
'path' => '',
|
||||
'query' => array(),
|
||||
'fragment' => '',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'https://',
|
||||
array(
|
||||
'path' => '',
|
||||
'query' => array(),
|
||||
'fragment' => '',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'/my/path?destination=home#footer',
|
||||
array(
|
||||
'path' => '/my/path',
|
||||
'query' => array(
|
||||
'destination' => 'home',
|
||||
),
|
||||
'fragment' => 'footer',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests path encoding.
|
||||
*
|
||||
* @dataProvider providerTestEncodePath
|
||||
* @covers ::encodePath
|
||||
*
|
||||
* @param string $path
|
||||
* A path to encode.
|
||||
* @param string $expected
|
||||
* The expected encoded path.
|
||||
*/
|
||||
public function testEncodePath($path, $expected) {
|
||||
$encoded = UrlHelper::encodePath($path);
|
||||
$this->assertEquals($expected, $encoded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testEncodePath().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function providerTestEncodePath() {
|
||||
return array(
|
||||
array('unencoded path with spaces', 'unencoded%20path%20with%20spaces'),
|
||||
array('slashes/should/be/preserved', 'slashes/should/be/preserved'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests external versus internal paths.
|
||||
*
|
||||
* @dataProvider providerTestIsExternal
|
||||
* @covers ::isExternal
|
||||
*
|
||||
* @param string $path
|
||||
* URL or path to test.
|
||||
* @param bool $expected
|
||||
* Expected result.
|
||||
*/
|
||||
public function testIsExternal($path, $expected) {
|
||||
$isExternal = UrlHelper::isExternal($path);
|
||||
$this->assertEquals($expected, $isExternal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testIsExternal().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function providerTestIsExternal() {
|
||||
return array(
|
||||
array('/internal/path', FALSE),
|
||||
array('https://example.com/external/path', TRUE),
|
||||
array('javascript://fake-external-path', FALSE),
|
||||
// External URL without an explicit protocol.
|
||||
array('//www.drupal.org/foo/bar?foo=bar&bar=baz&baz#foo', TRUE),
|
||||
// Internal URL starting with a slash.
|
||||
array('/www.drupal.org', FALSE),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests bad protocol filtering and escaping.
|
||||
*
|
||||
* @dataProvider providerTestFilterBadProtocol
|
||||
* @covers ::setAllowedProtocols
|
||||
* @covers ::filterBadProtocol
|
||||
*
|
||||
* @param string $uri
|
||||
* Protocol URI.
|
||||
* @param string $expected
|
||||
* Expected escaped value.
|
||||
* @param array $protocols
|
||||
* Protocols to allow.
|
||||
*/
|
||||
public function testFilterBadProtocol($uri, $expected, $protocols) {
|
||||
UrlHelper::setAllowedProtocols($protocols);
|
||||
$filtered = UrlHelper::filterBadProtocol($uri);
|
||||
$this->assertEquals($expected, $filtered);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testTestFilterBadProtocol().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function providerTestFilterBadProtocol() {
|
||||
return array(
|
||||
array('javascript://example.com?foo&bar', '//example.com?foo&bar', array('http', 'https')),
|
||||
// Test custom protocols.
|
||||
array('http://example.com?foo&bar', '//example.com?foo&bar', array('https')),
|
||||
// Valid protocol.
|
||||
array('http://example.com?foo&bar', 'http://example.com?foo&bar', array('https', 'http')),
|
||||
// Colon not part of the URL scheme.
|
||||
array('/test:8888?foo&bar', '/test:8888?foo&bar', array('http')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests dangerous url protocol filtering.
|
||||
*
|
||||
* @dataProvider providerTestStripDangerousProtocols
|
||||
* @covers ::setAllowedProtocols
|
||||
* @covers ::stripDangerousProtocols
|
||||
*
|
||||
* @param string $uri
|
||||
* Protocol URI.
|
||||
* @param string $expected
|
||||
* Expected escaped value.
|
||||
* @param array $protocols
|
||||
* Protocols to allow.
|
||||
*/
|
||||
public function testStripDangerousProtocols($uri, $expected, $protocols) {
|
||||
UrlHelper::setAllowedProtocols($protocols);
|
||||
$stripped = UrlHelper::stripDangerousProtocols($uri);
|
||||
$this->assertEquals($expected, $stripped);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testStripDangerousProtocols().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function providerTestStripDangerousProtocols() {
|
||||
return array(
|
||||
array('javascript://example.com', '//example.com', array('http', 'https')),
|
||||
// Test custom protocols.
|
||||
array('http://example.com', '//example.com', array('https')),
|
||||
// Valid protocol.
|
||||
array('http://example.com', 'http://example.com', array('https', 'http')),
|
||||
// Colon not part of the URL scheme.
|
||||
array('/test:8888', '/test:8888', array('http')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhances test urls with schemes
|
||||
*
|
||||
* @param array $urls
|
||||
* The list of urls.
|
||||
*
|
||||
* @return array
|
||||
* A list of provider data with schemes.
|
||||
*/
|
||||
protected function dataEnhanceWithScheme(array $urls) {
|
||||
$url_schemes = array('http', 'https', 'ftp');
|
||||
$data = array();
|
||||
foreach ($url_schemes as $scheme) {
|
||||
foreach ($urls as $url) {
|
||||
$data[] = array($url, $scheme);
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhances test urls with prefixes.
|
||||
*
|
||||
* @param array $urls
|
||||
* The list of urls.
|
||||
*
|
||||
* @return array
|
||||
* A list of provider data with prefixes.
|
||||
*/
|
||||
protected function dataEnhanceWithPrefix(array $urls) {
|
||||
$prefixes = array('', '/');
|
||||
$data = array();
|
||||
foreach ($prefixes as $prefix) {
|
||||
foreach ($urls as $url) {
|
||||
$data[] = array($url, $prefix);
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test detecting external urls that point to local resources.
|
||||
*
|
||||
* @param string $url
|
||||
* The external url to test.
|
||||
* @param string $base_url
|
||||
* The base url.
|
||||
* @param bool $expected
|
||||
* TRUE if an external URL points to this installation as determined by the
|
||||
* base url.
|
||||
*
|
||||
* @covers ::externalIsLocal
|
||||
* @dataProvider providerTestExternalIsLocal
|
||||
*/
|
||||
public function testExternalIsLocal($url, $base_url, $expected) {
|
||||
$this->assertSame($expected, UrlHelper::externalIsLocal($url, $base_url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for local external url detection.
|
||||
*
|
||||
* @see \Drupal\Tests\Component\Utility\UrlHelperTest::testExternalIsLocal()
|
||||
*/
|
||||
public function providerTestExternalIsLocal() {
|
||||
return array(
|
||||
// Different mixes of trailing slash.
|
||||
array('http://example.com', 'http://example.com', TRUE),
|
||||
array('http://example.com/', 'http://example.com', TRUE),
|
||||
array('http://example.com', 'http://example.com/', TRUE),
|
||||
array('http://example.com/', 'http://example.com/', TRUE),
|
||||
// Sub directory of site.
|
||||
array('http://example.com/foo', 'http://example.com/', TRUE),
|
||||
array('http://example.com/foo/bar', 'http://example.com/foo', TRUE),
|
||||
array('http://example.com/foo/bar', 'http://example.com/foo/', TRUE),
|
||||
// Different sub-domain.
|
||||
array('http://example.com', 'http://www.example.com/', FALSE),
|
||||
array('http://example.com/', 'http://www.example.com/', FALSE),
|
||||
array('http://example.com/foo', 'http://www.example.com/', FALSE),
|
||||
// Different TLD.
|
||||
array('http://example.com', 'http://example.ca', FALSE),
|
||||
array('http://example.com', 'http://example.ca/', FALSE),
|
||||
array('http://example.com/', 'http://example.ca/', FALSE),
|
||||
array('http://example.com/foo', 'http://example.ca', FALSE),
|
||||
array('http://example.com/foo', 'http://example.ca/', FALSE),
|
||||
// Different site path.
|
||||
array('http://example.com/foo', 'http://example.com/bar', FALSE),
|
||||
array('http://example.com', 'http://example.com/bar', FALSE),
|
||||
array('http://example.com/bar', 'http://example.com/bar/', FALSE),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test invalid url arguments.
|
||||
*
|
||||
* @param string $url
|
||||
* The url to test.
|
||||
* @param string $base_url
|
||||
* The base url.
|
||||
*
|
||||
* @covers ::externalIsLocal
|
||||
* @dataProvider providerTestExternalIsLocalInvalid
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testExternalIsLocalInvalid($url, $base_url) {
|
||||
UrlHelper::externalIsLocal($url, $base_url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides invalid argument data for local external url detection.
|
||||
*
|
||||
* @see \Drupal\Tests\Component\Utility\UrlHelperTest::testExternalIsLocalInvalid()
|
||||
*/
|
||||
public function providerTestExternalIsLocalInvalid() {
|
||||
return array(
|
||||
array('http://example.com/foo', ''),
|
||||
array('http://example.com/foo', 'bar'),
|
||||
array('http://example.com/foo', 'http://'),
|
||||
// Invalid destination urls.
|
||||
array('', 'http://example.com/foo'),
|
||||
array('bar', 'http://example.com/foo'),
|
||||
array('/bar', 'http://example.com/foo'),
|
||||
array('bar/', 'http://example.com/foo'),
|
||||
array('http://', 'http://example.com/foo'),
|
||||
);
|
||||
}
|
||||
}
|
172
core/tests/Drupal/Tests/Component/Utility/UserAgentTest.php
Normal file
172
core/tests/Drupal/Tests/Component/Utility/UserAgentTest.php
Normal file
|
@ -0,0 +1,172 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\UserAgentTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\UserAgent;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests bytes size parsing helper methods.
|
||||
*
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\UserAgent
|
||||
*/
|
||||
class UserAgentTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Helper method to supply language codes to testGetBestMatchingLangcode().
|
||||
*
|
||||
* @return array
|
||||
* Language codes, ordered by priority.
|
||||
*/
|
||||
protected function getLanguages() {
|
||||
return array(
|
||||
// In our test case, 'en' has priority over 'en-US'.
|
||||
'en',
|
||||
'en-US',
|
||||
// But 'fr-CA' has priority over 'fr'.
|
||||
'fr-CA',
|
||||
'fr',
|
||||
// 'es-MX' is alone.
|
||||
'es-MX',
|
||||
// 'pt' is alone.
|
||||
'pt',
|
||||
// Language codes with more then one dash are actually valid.
|
||||
// eh-oh-laa-laa is the official language code of the Teletubbies.
|
||||
'eh-oh-laa-laa',
|
||||
// Chinese languages.
|
||||
'zh-hans',
|
||||
'zh-hant',
|
||||
'zh-hant-tw',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to supply language mappings to testGetBestMatchingLangcode().
|
||||
*
|
||||
* @return array
|
||||
* Language mappings.
|
||||
*/
|
||||
protected function getMappings() {
|
||||
return array(
|
||||
'no' => 'nb',
|
||||
'pt' => 'pt-pt',
|
||||
'zh' => 'zh-hans',
|
||||
'zh-tw' => 'zh-hant',
|
||||
'zh-hk' => 'zh-hant',
|
||||
'zh-mo' => 'zh-hant',
|
||||
'zh-cht' => 'zh-hant',
|
||||
'zh-cn' => 'zh-hans',
|
||||
'zh-sg' => 'zh-hans',
|
||||
'zh-chs' => 'zh-hans',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test matching language from user agent.
|
||||
*
|
||||
* @dataProvider providerTestGetBestMatchingLangcode
|
||||
* @covers ::getBestMatchingLangcode
|
||||
*/
|
||||
public function testGetBestMatchingLangcode($accept_language, $expected) {
|
||||
$result = UserAgent::getBestMatchingLangcode($accept_language, $this->getLanguages(), $this->getMappings());
|
||||
$this->assertSame($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testGetBestMatchingLangcode().
|
||||
*
|
||||
* @return array
|
||||
* - An accept-language string.
|
||||
* - Expected best matching language code.
|
||||
*/
|
||||
public function providerTestGetBestMatchingLangcode() {
|
||||
return array(
|
||||
// Equal qvalue for each language, choose the site preferred one.
|
||||
array('en,en-US,fr-CA,fr,es-MX', 'en'),
|
||||
array('en-US,en,fr-CA,fr,es-MX', 'en'),
|
||||
array('fr,en', 'en'),
|
||||
array('en,fr', 'en'),
|
||||
array('en-US,fr', 'en-US'),
|
||||
array('fr,en-US', 'en-US'),
|
||||
array('fr,fr-CA', 'fr-CA'),
|
||||
array('fr-CA,fr', 'fr-CA'),
|
||||
array('fr', 'fr-CA'),
|
||||
array('fr;q=1', 'fr-CA'),
|
||||
array('fr,es-MX', 'fr-CA'),
|
||||
array('fr,es', 'fr-CA'),
|
||||
array('es,fr', 'fr-CA'),
|
||||
array('es-MX,de', 'es-MX'),
|
||||
array('de,es-MX', 'es-MX'),
|
||||
|
||||
// Different cases and whitespace.
|
||||
array('en', 'en'),
|
||||
array('En', 'en'),
|
||||
array('EN', 'en'),
|
||||
array(' en', 'en'),
|
||||
array('en ', 'en'),
|
||||
array('en, fr', 'en'),
|
||||
|
||||
// A less specific language from the browser matches a more specific one
|
||||
// from the website, and the other way around for compatibility with
|
||||
// some versions of Internet Explorer.
|
||||
array('es', 'es-MX'),
|
||||
array('es-MX', 'es-MX'),
|
||||
array('pt', 'pt'),
|
||||
array('pt-PT', 'pt'),
|
||||
array('pt-PT;q=0.5,pt-BR;q=1,en;q=0.7', 'en'),
|
||||
array('pt-PT;q=1,pt-BR;q=0.5,en;q=0.7', 'en'),
|
||||
array('pt-PT;q=0.4,pt-BR;q=0.1,en;q=0.7', 'en'),
|
||||
array('pt-PT;q=0.1,pt-BR;q=0.4,en;q=0.7', 'en'),
|
||||
|
||||
// Language code with several dashes are valid. The less specific language
|
||||
// from the browser matches the more specific one from the website.
|
||||
array('eh-oh-laa-laa', 'eh-oh-laa-laa'),
|
||||
array('eh-oh-laa', 'eh-oh-laa-laa'),
|
||||
array('eh-oh', 'eh-oh-laa-laa'),
|
||||
array('eh', 'eh-oh-laa-laa'),
|
||||
|
||||
// Different qvalues.
|
||||
array('fr,en;q=0.5', 'fr-CA'),
|
||||
array('fr,en;q=0.5,fr-CA;q=0.25', 'fr'),
|
||||
|
||||
// Silly wildcards are also valid.
|
||||
array('*,fr-CA;q=0.5', 'en'),
|
||||
array('*,en;q=0.25', 'fr-CA'),
|
||||
array('en,en-US;q=0.5,fr;q=0.25', 'en'),
|
||||
array('en-US,en;q=0.5,fr;q=0.25', 'en-US'),
|
||||
|
||||
// Unresolvable cases.
|
||||
array('', FALSE),
|
||||
array('de,pl', FALSE),
|
||||
array('iecRswK4eh', FALSE),
|
||||
array($this->randomMachineName(10), FALSE),
|
||||
|
||||
// Chinese langcodes.
|
||||
array('zh-cn, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hans'),
|
||||
array('zh-tw, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hant'),
|
||||
array('zh-hant, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hant'),
|
||||
array('zh-hans, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hans'),
|
||||
// @todo: This is copied from RFC4647 but our regex skips the numbers so
|
||||
// they where removed. Our code should be updated so private1-private2 is
|
||||
// valid. http://tools.ietf.org/html/rfc4647#section-3.4
|
||||
array('zh-hant-CN-x-private-private, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hant'),
|
||||
array('zh-cn', 'zh-hans'),
|
||||
array('zh-sg', 'zh-hans'),
|
||||
array('zh-tw', 'zh-hant'),
|
||||
array('zh-hk', 'zh-hant'),
|
||||
array('zh-mo', 'zh-hant'),
|
||||
array('zh-hans', 'zh-hans'),
|
||||
array('zh-hant', 'zh-hant'),
|
||||
array('zh-chs', 'zh-hans'),
|
||||
array('zh-cht', 'zh-hant'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
120
core/tests/Drupal/Tests/Component/Utility/VariableTest.php
Normal file
120
core/tests/Drupal/Tests/Component/Utility/VariableTest.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\VariableTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Component\Utility\Variable;
|
||||
|
||||
/**
|
||||
* Test variable export functionality in Variable component.
|
||||
*
|
||||
* @group Variable
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Variable
|
||||
*/
|
||||
class VariableTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Data provider for testExport().
|
||||
*
|
||||
* @return array
|
||||
* An array containing:
|
||||
* - The expected export string.
|
||||
* - The variable to export.
|
||||
*/
|
||||
public function providerTestExport() {
|
||||
return array(
|
||||
// Array.
|
||||
array(
|
||||
'array()',
|
||||
array(),
|
||||
),
|
||||
array(
|
||||
// non-associative.
|
||||
"array(\n 1,\n 2,\n 3,\n 4,\n)",
|
||||
array(1, 2, 3, 4),
|
||||
),
|
||||
array(
|
||||
// associative.
|
||||
"array(\n 'a' => 1,\n)",
|
||||
array('a' => 1),
|
||||
),
|
||||
// Bool.
|
||||
array(
|
||||
'TRUE',
|
||||
TRUE,
|
||||
),
|
||||
array(
|
||||
'FALSE',
|
||||
FALSE,
|
||||
),
|
||||
// Strings.
|
||||
array(
|
||||
"'string'",
|
||||
'string',
|
||||
),
|
||||
array(
|
||||
'"\n\r\t"',
|
||||
"\n\r\t",
|
||||
),
|
||||
array(
|
||||
// 2 backslashes. \\
|
||||
"'\\'",
|
||||
'\\',
|
||||
),
|
||||
array(
|
||||
// Double-quote "
|
||||
"'\"'",
|
||||
"\"",
|
||||
),
|
||||
array(
|
||||
// Single-quote '
|
||||
'"\'"',
|
||||
"'",
|
||||
),
|
||||
// Object.
|
||||
array(
|
||||
// A stdClass object.
|
||||
'(object) array()',
|
||||
new \stdClass(),
|
||||
),
|
||||
array(
|
||||
// A not-stdClass object.
|
||||
"Drupal\Tests\Component\Utility\StubVariableTestClass::__set_state(array(\n))",
|
||||
new StubVariableTestClass(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests exporting variables.
|
||||
*
|
||||
* @dataProvider providerTestExport
|
||||
* @covers ::export
|
||||
*
|
||||
* @param string $expected
|
||||
* The expected exported variable.
|
||||
* @param mixed $variable
|
||||
* The variable to be exported.
|
||||
*/
|
||||
public function testExport($expected, $variable) {
|
||||
$this->assertEquals($expected, Variable::export($variable));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* No-op test class for VariableTest::testExport().
|
||||
*
|
||||
* @see Drupal\Tests\Component\Utility\VariableTest::testExport()
|
||||
* @see Drupal\Tests\Component\Utility\VariableTest::providerTestExport()
|
||||
*/
|
||||
class StubVariableTestClass {
|
||||
|
||||
}
|
609
core/tests/Drupal/Tests/Component/Utility/XssTest.php
Normal file
609
core/tests/Drupal/Tests/Component/Utility/XssTest.php
Normal file
|
@ -0,0 +1,609 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\XssTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\UrlHelper;
|
||||
use Drupal\Component\Utility\Xss;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* XSS Filtering tests.
|
||||
*
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Xss
|
||||
*
|
||||
* Script injection vectors mostly adopted from http://ha.ckers.org/xss.html.
|
||||
*
|
||||
* Relevant CVEs:
|
||||
* - CVE-2002-1806, ~CVE-2005-0682, ~CVE-2005-2106, CVE-2005-3973,
|
||||
* CVE-2006-1226 (= rev. 1.112?), CVE-2008-0273, CVE-2008-3740.
|
||||
*/
|
||||
class XssTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$allowed_protocols = array(
|
||||
'http',
|
||||
'https',
|
||||
'ftp',
|
||||
'news',
|
||||
'nntp',
|
||||
'telnet',
|
||||
'mailto',
|
||||
'irc',
|
||||
'ssh',
|
||||
'sftp',
|
||||
'webcal',
|
||||
'rtsp',
|
||||
);
|
||||
UrlHelper::setAllowedProtocols($allowed_protocols);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests limiting allowed tags and XSS prevention.
|
||||
*
|
||||
* XSS tests assume that script is disallowed by default and src is allowed
|
||||
* by default, but on* and style attributes are disallowed.
|
||||
*
|
||||
* @param string $value
|
||||
* The value to filter.
|
||||
* @param string $expected
|
||||
* The expected result.
|
||||
* @param string $message
|
||||
* The assertion message to display upon failure.
|
||||
* @param array $allowed_tags
|
||||
* (optional) The allowed HTML tags to be passed to \Drupal\Component\Utility\Xss::filter().
|
||||
*
|
||||
* @dataProvider providerTestFilterXssNormalized
|
||||
*/
|
||||
public function testFilterXssNormalized($value, $expected, $message, array $allowed_tags = NULL) {
|
||||
if ($allowed_tags === NULL) {
|
||||
$value = Xss::filter($value);
|
||||
}
|
||||
else {
|
||||
$value = Xss::filter($value, $allowed_tags);
|
||||
}
|
||||
$this->assertNormalized($value, $expected, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testFilterXssNormalized().
|
||||
*
|
||||
* @see testFilterXssNormalized()
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays containing strings:
|
||||
* - The value to filter.
|
||||
* - The value to expect after filtering.
|
||||
* - The assertion message.
|
||||
* - (optional) The allowed HTML HTML tags array that should be passed to
|
||||
* \Drupal\Component\Utility\Xss::filter().
|
||||
*/
|
||||
public function providerTestFilterXssNormalized() {
|
||||
return array(
|
||||
array(
|
||||
"Who's Online",
|
||||
"who's online",
|
||||
'HTML filter -- html entity number',
|
||||
),
|
||||
array(
|
||||
"Who&#039;s Online",
|
||||
"who's online",
|
||||
'HTML filter -- encoded html entity number',
|
||||
),
|
||||
array(
|
||||
"Who&amp;#039; Online",
|
||||
"who&#039; online",
|
||||
'HTML filter -- double encoded html entity number',
|
||||
),
|
||||
// Custom elements with dashes in the tag name.
|
||||
array(
|
||||
"<test-element></test-element>",
|
||||
"<test-element></test-element>",
|
||||
'Custom element with dashes in tag name.',
|
||||
array('test-element'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests limiting to allowed tags and XSS prevention.
|
||||
*
|
||||
* XSS tests assume that script is disallowed by default and src is allowed
|
||||
* by default, but on* and style attributes are disallowed.
|
||||
*
|
||||
* @param string $value
|
||||
* The value to filter.
|
||||
* @param string $expected
|
||||
* The string that is expected to be missing.
|
||||
* @param string $message
|
||||
* The assertion message to display upon failure.
|
||||
* @param array $allowed_tags
|
||||
* (optional) The allowed HTML tags to be passed to \Drupal\Component\Utility\Xss::filter().
|
||||
*
|
||||
* @dataProvider providerTestFilterXssNotNormalized
|
||||
*/
|
||||
public function testFilterXssNotNormalized($value, $expected, $message, array $allowed_tags = NULL) {
|
||||
if ($allowed_tags === NULL) {
|
||||
$value = Xss::filter($value);
|
||||
}
|
||||
else {
|
||||
$value = Xss::filter($value, $allowed_tags);
|
||||
}
|
||||
$this->assertNotNormalized($value, $expected, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testFilterXssNotNormalized().
|
||||
*
|
||||
* @see testFilterXssNotNormalized()
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays containing the following elements:
|
||||
* - The value to filter.
|
||||
* - The value to expect that's missing after filtering.
|
||||
* - The assertion message.
|
||||
* - (optional) The allowed HTML HTML tags array that should be passed to
|
||||
* \Drupal\Component\Utility\Xss::filter().
|
||||
*/
|
||||
public function providerTestFilterXssNotNormalized() {
|
||||
$cases = array(
|
||||
// Tag stripping, different ways to work around removal of HTML tags.
|
||||
array(
|
||||
'<script>alert(0)</script>',
|
||||
'script',
|
||||
'HTML tag stripping -- simple script without special characters.',
|
||||
),
|
||||
array(
|
||||
'<script src="http://www.example.com" />',
|
||||
'script',
|
||||
'HTML tag stripping -- empty script with source.',
|
||||
),
|
||||
array(
|
||||
'<ScRipt sRc=http://www.example.com/>',
|
||||
'script',
|
||||
'HTML tag stripping evasion -- varying case.',
|
||||
),
|
||||
array(
|
||||
"<script\nsrc\n=\nhttp://www.example.com/\n>",
|
||||
'script',
|
||||
'HTML tag stripping evasion -- multiline tag.',
|
||||
),
|
||||
array(
|
||||
'<script/a src=http://www.example.com/a.js></script>',
|
||||
'script',
|
||||
'HTML tag stripping evasion -- non whitespace character after tag name.',
|
||||
),
|
||||
array(
|
||||
'<script/src=http://www.example.com/a.js></script>',
|
||||
'script',
|
||||
'HTML tag stripping evasion -- no space between tag and attribute.',
|
||||
),
|
||||
// Null between < and tag name works at least with IE6.
|
||||
array(
|
||||
"<\0scr\0ipt>alert(0)</script>",
|
||||
'ipt',
|
||||
'HTML tag stripping evasion -- breaking HTML with nulls.',
|
||||
),
|
||||
array(
|
||||
"<scrscriptipt src=http://www.example.com/a.js>",
|
||||
'script',
|
||||
'HTML tag stripping evasion -- filter just removing "script".',
|
||||
),
|
||||
array(
|
||||
'<<script>alert(0);//<</script>',
|
||||
'script',
|
||||
'HTML tag stripping evasion -- double opening brackets.',
|
||||
),
|
||||
array(
|
||||
'<script src=http://www.example.com/a.js?<b>',
|
||||
'script',
|
||||
'HTML tag stripping evasion -- no closing tag.',
|
||||
),
|
||||
// DRUPAL-SA-2008-047: This doesn't seem exploitable, but the filter should
|
||||
// work consistently.
|
||||
array(
|
||||
'<script>>',
|
||||
'script',
|
||||
'HTML tag stripping evasion -- double closing tag.',
|
||||
),
|
||||
array(
|
||||
'<script src=//www.example.com/.a>',
|
||||
'script',
|
||||
'HTML tag stripping evasion -- no scheme or ending slash.',
|
||||
),
|
||||
array(
|
||||
'<script src=http://www.example.com/.a',
|
||||
'script',
|
||||
'HTML tag stripping evasion -- no closing bracket.',
|
||||
),
|
||||
array(
|
||||
'<script src=http://www.example.com/ <',
|
||||
'script',
|
||||
'HTML tag stripping evasion -- opening instead of closing bracket.',
|
||||
),
|
||||
array(
|
||||
'<nosuchtag attribute="newScriptInjectionVector">',
|
||||
'nosuchtag',
|
||||
'HTML tag stripping evasion -- unknown tag.',
|
||||
),
|
||||
array(
|
||||
'<t:set attributeName="innerHTML" to="<script defer>alert(0)</script>">',
|
||||
't:set',
|
||||
'HTML tag stripping evasion -- colon in the tag name (namespaces\' tricks).',
|
||||
),
|
||||
array(
|
||||
'<img """><script>alert(0)</script>',
|
||||
'script',
|
||||
'HTML tag stripping evasion -- a malformed image tag.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<blockquote><script>alert(0)</script></blockquote>',
|
||||
'script',
|
||||
'HTML tag stripping evasion -- script in a blockqoute.',
|
||||
array('blockquote'),
|
||||
),
|
||||
array(
|
||||
"<!--[if true]><script>alert(0)</script><![endif]-->",
|
||||
'script',
|
||||
'HTML tag stripping evasion -- script within a comment.',
|
||||
),
|
||||
// Dangerous attributes removal.
|
||||
array(
|
||||
'<p onmouseover="http://www.example.com/">',
|
||||
'onmouseover',
|
||||
'HTML filter attributes removal -- events, no evasion.',
|
||||
array('p'),
|
||||
),
|
||||
array(
|
||||
'<li style="list-style-image: url(javascript:alert(0))">',
|
||||
'style',
|
||||
'HTML filter attributes removal -- style, no evasion.',
|
||||
array('li'),
|
||||
),
|
||||
array(
|
||||
'<img onerror =alert(0)>',
|
||||
'onerror',
|
||||
'HTML filter attributes removal evasion -- spaces before equals sign.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img onabort!#$%&()*~+-_.,:;?@[/|\]^`=alert(0)>',
|
||||
'onabort',
|
||||
'HTML filter attributes removal evasion -- non alphanumeric characters before equals sign.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img oNmediAError=alert(0)>',
|
||||
'onmediaerror',
|
||||
'HTML filter attributes removal evasion -- varying case.',
|
||||
array('img'),
|
||||
),
|
||||
// Works at least with IE6.
|
||||
array(
|
||||
"<img o\0nfocus\0=alert(0)>",
|
||||
'focus',
|
||||
'HTML filter attributes removal evasion -- breaking with nulls.',
|
||||
array('img'),
|
||||
),
|
||||
// Only whitelisted scheme names allowed in attributes.
|
||||
array(
|
||||
'<img src="javascript:alert(0)">',
|
||||
'javascript',
|
||||
'HTML scheme clearing -- no evasion.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img src=javascript:alert(0)>',
|
||||
'javascript',
|
||||
'HTML scheme clearing evasion -- no quotes.',
|
||||
array('img'),
|
||||
),
|
||||
// A bit like CVE-2006-0070.
|
||||
array(
|
||||
'<img src="javascript:confirm(0)">',
|
||||
'javascript',
|
||||
'HTML scheme clearing evasion -- no alert ;)',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img src=`javascript:alert(0)`>',
|
||||
'javascript',
|
||||
'HTML scheme clearing evasion -- grave accents.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img dynsrc="javascript:alert(0)">',
|
||||
'javascript',
|
||||
'HTML scheme clearing -- rare attribute.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<table background="javascript:alert(0)">',
|
||||
'javascript',
|
||||
'HTML scheme clearing -- another tag.',
|
||||
array('table'),
|
||||
),
|
||||
array(
|
||||
'<base href="javascript:alert(0);//">',
|
||||
'javascript',
|
||||
'HTML scheme clearing -- one more attribute and tag.',
|
||||
array('base'),
|
||||
),
|
||||
array(
|
||||
'<img src="jaVaSCriPt:alert(0)">',
|
||||
'javascript',
|
||||
'HTML scheme clearing evasion -- varying case.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img src=javascript:alert(0)>',
|
||||
'javascript',
|
||||
'HTML scheme clearing evasion -- UTF-8 decimal encoding.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img src=javascript:alert(0)>',
|
||||
'javascript',
|
||||
'HTML scheme clearing evasion -- long UTF-8 encoding.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img src=javascript:alert(0)>',
|
||||
'javascript',
|
||||
'HTML scheme clearing evasion -- UTF-8 hex encoding.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
"<img src=\"jav\tascript:alert(0)\">",
|
||||
'script',
|
||||
'HTML scheme clearing evasion -- an embedded tab.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img src="jav	ascript:alert(0)">',
|
||||
'script',
|
||||
'HTML scheme clearing evasion -- an encoded, embedded tab.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img src="jav
ascript:alert(0)">',
|
||||
'script',
|
||||
'HTML scheme clearing evasion -- an encoded, embedded newline.',
|
||||
array('img'),
|
||||
),
|
||||
// With 
 this test would fail, but the entity gets turned into
|
||||
// &#xD;, so it's OK.
|
||||
array(
|
||||
'<img src="jav
ascript:alert(0)">',
|
||||
'script',
|
||||
'HTML scheme clearing evasion -- an encoded, embedded carriage return.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
"<img src=\"\n\n\nj\na\nva\ns\ncript:alert(0)\">",
|
||||
'cript',
|
||||
'HTML scheme clearing evasion -- broken into many lines.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
"<img src=\"jav\0a\0\0cript:alert(0)\">",
|
||||
'cript',
|
||||
'HTML scheme clearing evasion -- embedded nulls.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img src="vbscript:msgbox(0)">',
|
||||
'vbscript',
|
||||
'HTML scheme clearing evasion -- another scheme.',
|
||||
array('img'),
|
||||
),
|
||||
array(
|
||||
'<img src="nosuchscheme:notice(0)">',
|
||||
'nosuchscheme',
|
||||
'HTML scheme clearing evasion -- unknown scheme.',
|
||||
array('img'),
|
||||
),
|
||||
// Netscape 4.x javascript entities.
|
||||
array(
|
||||
'<br size="&{alert(0)}">',
|
||||
'alert',
|
||||
'Netscape 4.x javascript entities.',
|
||||
array('br'),
|
||||
),
|
||||
// DRUPAL-SA-2008-006: Invalid UTF-8, these only work as reflected XSS with
|
||||
// Internet Explorer 6.
|
||||
array(
|
||||
"<p arg=\"\xe0\">\" style=\"background-image: url(javascript:alert(0));\"\xe0<p>",
|
||||
'style',
|
||||
'HTML filter -- invalid UTF-8.',
|
||||
array('p'),
|
||||
),
|
||||
);
|
||||
// @fixme This dataset currently fails under 5.4 because of
|
||||
// https://www.drupal.org/node/1210798. Restore after its fixed.
|
||||
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
|
||||
$cases[] = array(
|
||||
'<img src="  javascript:alert(0)">',
|
||||
'javascript',
|
||||
'HTML scheme clearing evasion -- spaces and metacharacters before scheme.',
|
||||
array('img'),
|
||||
);
|
||||
}
|
||||
return $cases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that invalid multi-byte sequences are rejected.
|
||||
*
|
||||
* @param string $value
|
||||
* The value to filter.
|
||||
* @param string $expected
|
||||
* The expected result.
|
||||
* @param string $message
|
||||
* The assertion message to display upon failure.
|
||||
*
|
||||
* @dataProvider providerTestInvalidMultiByte
|
||||
*/
|
||||
public function testInvalidMultiByte($value, $expected, $message) {
|
||||
$this->assertEquals(Xss::filter($value), $expected, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testInvalidMultiByte().
|
||||
*
|
||||
* @see testInvalidMultiByte()
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays containing strings:
|
||||
* - The value to filter.
|
||||
* - The value to expect after filtering.
|
||||
* - The assertion message.
|
||||
*/
|
||||
public function providerTestInvalidMultiByte() {
|
||||
return array(
|
||||
array("Foo\xC0barbaz", '', 'Xss::filter() accepted invalid sequence "Foo\xC0barbaz"'),
|
||||
array("Fooÿñ", "Fooÿñ", 'Xss::filter() rejects valid sequence Fooÿñ"'),
|
||||
array("\xc0aaa", '', 'HTML filter -- overlong UTF-8 sequences.'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that strings starting with a question sign are correctly processed.
|
||||
*/
|
||||
public function testQuestionSign() {
|
||||
$value = Xss::filter('<?xml:namespace ns="urn:schemas-microsoft-com:time">');
|
||||
$this->assertTrue(stripos($value, '<?xml') === FALSE, 'HTML tag stripping evasion -- starting with a question sign (processing instructions).');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that strings in HTML attributes are are correctly processed.
|
||||
*
|
||||
* @covers ::attributes
|
||||
* @dataProvider providerTestAttributes
|
||||
*/
|
||||
public function testAttribute($value, $expected, $message, $allowed_tags = NULL) {
|
||||
$value = Xss::filter($value, $allowed_tags);
|
||||
$this->assertEquals($expected, $value, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testFilterXssAdminNotNormalized().
|
||||
*/
|
||||
public function providerTestAttributes() {
|
||||
return array(
|
||||
array(
|
||||
'<img src="http://example.com/foo.jpg" title="Example: title" alt="Example: alt">',
|
||||
'<img src="http://example.com/foo.jpg" title="Example: title" alt="Example: alt">',
|
||||
'Image tag with alt and title attribute',
|
||||
array('img')
|
||||
),
|
||||
array(
|
||||
'<img src="http://example.com/foo.jpg" data-caption="Drupal 8: The best release ever.">',
|
||||
'<img src="http://example.com/foo.jpg" data-caption="Drupal 8: The best release ever.">',
|
||||
'Image tag with data attribute',
|
||||
array('img')
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that \Drupal\Component\Utility\Xss::filterAdmin() correctly strips unallowed tags.
|
||||
*/
|
||||
public function testFilterXSSAdmin() {
|
||||
$value = Xss::filterAdmin('<style /><iframe /><frame /><frameset /><meta /><link /><embed /><applet /><param /><layer />');
|
||||
$this->assertEquals($value, '', 'Admin HTML filter -- should never allow some tags.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the loose, admin HTML filter.
|
||||
*
|
||||
* @param string $value
|
||||
* The value to filter.
|
||||
* @param string $expected
|
||||
* The expected result.
|
||||
* @param string $message
|
||||
* The assertion message to display upon failure.
|
||||
*
|
||||
* @dataProvider providerTestFilterXssAdminNotNormalized
|
||||
*/
|
||||
public function testFilterXssAdminNotNormalized($value, $expected, $message) {
|
||||
$this->assertNotNormalized(Xss::filterAdmin($value), $expected, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testFilterXssAdminNotNormalized().
|
||||
*
|
||||
* @see testFilterXssAdminNotNormalized()
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays containing strings:
|
||||
* - The value to filter.
|
||||
* - The value to expect after filtering.
|
||||
* - The assertion message.
|
||||
*/
|
||||
public function providerTestFilterXssAdminNotNormalized() {
|
||||
return array(
|
||||
// DRUPAL-SA-2008-044
|
||||
array('<object />', 'object', 'Admin HTML filter -- should not allow object tag.'),
|
||||
array('<script />', 'script', 'Admin HTML filter -- should not allow script tag.'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a text transformed to lowercase with HTML entities decoded does contain a given string.
|
||||
*
|
||||
* Otherwise fails the test with a given message, similar to all the
|
||||
* SimpleTest assert* functions.
|
||||
*
|
||||
* Note that this does not remove nulls, new lines and other characters that
|
||||
* could be used to obscure a tag or an attribute name.
|
||||
*
|
||||
* @param string $haystack
|
||||
* Text to look in.
|
||||
* @param string $needle
|
||||
* Lowercase, plain text to look for.
|
||||
* @param string $message
|
||||
* (optional) Message to display if failed. Defaults to an empty string.
|
||||
* @param string $group
|
||||
* (optional) The group this message belongs to. Defaults to 'Other'.
|
||||
*/
|
||||
protected function assertNormalized($haystack, $needle, $message = '', $group = 'Other') {
|
||||
$this->assertTrue(strpos(strtolower(Html::decodeEntities($haystack)), $needle) !== FALSE, $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that text transformed to lowercase with HTML entities decoded does not contain a given string.
|
||||
*
|
||||
* Otherwise fails the test with a given message, similar to all the
|
||||
* SimpleTest assert* functions.
|
||||
*
|
||||
* Note that this does not remove nulls, new lines, and other character that
|
||||
* could be used to obscure a tag or an attribute name.
|
||||
*
|
||||
* @param string $haystack
|
||||
* Text to look in.
|
||||
* @param string $needle
|
||||
* Lowercase, plain text to look for.
|
||||
* @param string $message
|
||||
* (optional) Message to display if failed. Defaults to an empty string.
|
||||
* @param string $group
|
||||
* (optional) The group this message belongs to. Defaults to 'Other'.
|
||||
*/
|
||||
protected function assertNotNormalized($haystack, $needle, $message = '', $group = 'Other') {
|
||||
$this->assertTrue(strpos(strtolower(Html::decodeEntities($haystack)), $needle) === FALSE, $message, $group);
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue