summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Pott2015-07-21 13:29:05 (GMT)
committerAlex Pott2015-07-21 13:29:05 (GMT)
commitcc34748c31e393e25f595f472c1a40bedd9acf12 (patch)
treef2978ea02df07dd3bf6f88e6bb09376e3870acb1
parent4b36aab5fadf9dc63c87bcbaffe777825f9ea431 (diff)
Issue #2408013 by Aki Tendo, alexpott, Fabianx, dawehner, Crell, jhodgdon, Wim Leers, aspilicious: Adding Assertions to Drupal - Test Tools
-rw-r--r--.htaccess3
-rw-r--r--core/core.api.php50
-rw-r--r--core/lib/Drupal/Component/Assertion/Inspector.php409
-rw-r--r--core/tests/Drupal/Tests/Component/Assertion/InspectorTest.php241
-rw-r--r--sites/example.settings.local.php18
5 files changed, 720 insertions, 1 deletions
diff --git a/.htaccess b/.htaccess
index af418c4..73ce26b 100644
--- a/.htaccess
+++ b/.htaccess
@@ -28,13 +28,14 @@ DirectoryIndex index.php index.html index.htm
AddType image/svg+xml svg svgz
AddEncoding gzip svgz
-# Override PHP settings that cannot be changed at runtime. See
+# Most of the following PHP settings cannot be changed at runtime. See
# sites/default/default.settings.php and
# Drupal\Core\DrupalKernel::bootEnvironment() for settings that can be
# changed at runtime.
# PHP 5, Apache 1 and 2.
<IfModule mod_php5.c>
+ php_value assert.active 0
php_flag session.auto_start off
php_value mbstring.http_input pass
php_value mbstring.http_output pass
diff --git a/core/core.api.php b/core/core.api.php
index 63fd607..c34ca0e 100644
--- a/core/core.api.php
+++ b/core/core.api.php
@@ -57,6 +57,7 @@
* - @link queue Queue API @endlink
* - @link typed_data Typed Data @endlink
* - @link testing Automated tests @endlink
+ * - @link php_assert PHP Runtime Assert Statements @endlink
* - @link third_party Integrating third-party applications @endlink
*
* @section more_info Further information
@@ -983,6 +984,55 @@
*/
/**
+ * @defgroup php_assert PHP Runtime Assert Statements
+ * @{
+ * Use of the assert() statement in Drupal.
+ *
+ * Unit tests also use the term "assertion" to refer to test conditions, so to
+ * avoid confusion the term "runtime assertion" will be used for the assert()
+ * statement throughout the documentation.
+ *
+ * A runtime assertion is a statement that is expected to always be true at
+ * the point in the code it appears at. They are tested using PHP's internal
+ * @link http://www.php.net/assert assert() @endlink statement. If an
+ * assertion is ever FALSE it indicates an error in the code or in module or
+ * theme configuration files. User-provided configuration files should be
+ * verified with standard control structures at all times, not just checked in
+ * development environments with assert() statements on.
+ *
+ * When runtime assertions fail in PHP 7 an \AssertionException is thrown.
+ * Drupal uses an assertion callback to do the same in PHP 5.x so that unit
+ * tests involving runtime assertions will work uniformly across both versions.
+ *
+ * The Drupal project primarily uses runtime assertions to enforce the
+ * expectations of the API by failing when incorrect calls are made by code
+ * under development. While PHP type hinting does this for objects and arrays,
+ * runtime assertions do this for scalars (strings, integers, floats, etc.) and
+ * complex data structures such as cache and render arrays. They ensure that
+ * methods' return values are the documented datatypes. They also verify that
+ * objects have been properly configured and set up by the service container.
+ * Runtime assertions are checked throughout development. They supplement unit
+ * tests by checking scenarios that do not have unit tests written for them,
+ * and by testing the API calls made by all the code in the system.
+ *
+ * When using assert() keep the following in mind:
+ * - Runtime assertions are disabled by default in production and enabled in
+ * development, so they can't be used as control structures. Use exceptions
+ * for errors that can occur in production no matter how unlikely they are.
+ * - Assert() functions in a buggy manner prior to PHP 7. If you do not use a
+ * string for the first argument of the statement but instead use a function
+ * call or expression then that code will be evaluated even when runtime
+ * assertions are turned off. To avoid this you must use a string as the
+ * first argument, and assert will pass this string to the eval() statement.
+ * - Since runtime assertion strings are parsed by eval() use caution when
+ * using them to work with data that may be unsanitized.
+ *
+ * See https://www.drupal.org/node/2492225 for more information on runtime
+ * assertions.
+ * @}
+ */
+
+/**
* @defgroup info_types Information types
* @{
* Types of information in Drupal.
diff --git a/core/lib/Drupal/Component/Assertion/Inspector.php b/core/lib/Drupal/Component/Assertion/Inspector.php
new file mode 100644
index 0000000..cb17632
--- /dev/null
+++ b/core/lib/Drupal/Component/Assertion/Inspector.php
@@ -0,0 +1,409 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\Component\Assertion\Inspector.
+ */
+
+namespace Drupal\Component\Assertion;
+
+use Traversable;
+
+/**
+ * Generic inspections for the assert() statement.
+ *
+ * This is a static function collection for inspecting variable contents. All
+ * functions in this collection check a variable against an assertion about its
+ * structure.
+ *
+ * Example call:
+ * @code
+ * assert('Drupal\\Component\\Assertion\\Inspector::assertAllStrings($array)');
+ * @endcode
+ *
+ * @ingroup php_assert
+ */
+class Inspector {
+
+ /**
+ * Asserts argument can be traversed with foreach.
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed with foreach.
+ */
+ public static function assertTraversable($traversable) {
+ return is_array($traversable) || $traversable instanceof Traversable;
+ }
+
+ /**
+ * Asserts callback returns TRUE for each member of a traversable.
+ *
+ * This is less memory intensive than using array_filter() to build a second
+ * array and then comparing the arrays. Many of the other functions in this
+ * collection alias this function passing a specific callback to make the
+ * code more readable.
+ *
+ * @param callable $callable
+ * Callback function.
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and $callable returns TRUE on
+ * all members.
+ *
+ * @see http://php.net/manual/language.types.callable.php
+ */
+ public static function assertAll(callable $callable, $traversable) {
+ if (static::assertTraversable($traversable)) {
+ foreach ($traversable as $member) {
+ if (!$callable($member)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Asserts that all members are strings.
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members are strings.
+ */
+ public static function assertAllStrings($traversable) {
+ return static::assertAll('is_string', $traversable);
+ }
+
+ /**
+ * Asserts all members are strings or objects with magic __toString() method.
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members are strings or
+ * objects with __toString().
+ */
+ public static function assertAllStringable($traversable) {
+ if (static::assertTraversable($traversable)) {
+ foreach ($traversable as $member) {
+ if (!(is_string($member) || (is_object($member) && method_exists($member, '__toString')))) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Asserts that all members are arrays.
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members are arrays.
+ */
+ public static function assertAllArrays($traversable) {
+ return static::assertAll('is_array', $traversable);
+ }
+
+ /**
+ * Asserts that the array is strict.
+ *
+ * What PHP calls arrays are more formally called maps in most other
+ * programming languages. A map is a datatype that associates values to keys.
+ * The term 'strict array' here refers to a 0-indexed array in the classic
+ * sense found in programming languages other than PHP.
+ *
+ * @param mixed $array
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable is a 0-indexed array.
+ *
+ * @see http://php.net/manual/language.types.array.php
+ */
+ public static function assertStrictArray($array) {
+ if (!is_array($array)) {
+ return FALSE;
+ }
+ $i = 0;
+
+ foreach (array_keys($array) as $key) {
+ if ($i !== $key) {
+ return FALSE;
+ }
+ $i++;
+ }
+ return TRUE;
+ }
+
+ /**
+ * Asserts all members are strict arrays.
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members are strict arrays.
+ *
+ * @see ::assertStrictArray
+ */
+ public static function assertAllStrictArrays($traversable) {
+ return static::assertAll([__CLASS__, 'assertStrictArray'], $traversable);
+ }
+
+ /**
+ * Asserts all given keys exist in every member array.
+ *
+ * Drupal has several data structure arrays that require certain keys be set.
+ * You can overload this function to specify a list of required keys. All
+ * of the keys must be set for this method to return TRUE.
+ *
+ * As an example, this assertion tests for the keys of a theme registry.
+ *
+ * @code
+ * assert('Drupal\\Component\\Assertion\\Inspector::assertAllHaveKey(
+ * $arrayToTest, "type", "theme path", "function", "template", "variables", "render element", "preprocess functions")');
+ * @endcode
+ *
+ * Note: If a method requires certain keys to be present it will usually be
+ * specific about the data types for the values of those keys. Therefore it
+ * will be best to write a specific test for it. Such tests are either bound
+ * to the object that uses them, or are collected into one assertion set for
+ * the package.
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ * @param string ...
+ * Keys to be searched for.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members have all keys.
+ */
+ public static function assertAllHaveKey() {
+ $args = func_get_args();
+ $traversable = array_shift($args);
+
+ if (static::assertTraversable($traversable)) {
+ foreach ($traversable as $member) {
+ foreach ($args as $key) {
+ if (!array_key_exists($key, $member)) {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Asserts that all members are integer values.
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members are integers.
+ */
+ public static function assertAllIntegers($traversable) {
+ return static::assertAll('is_int', $traversable);
+ }
+
+ /**
+ * Asserts that all members are float values.
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members are floating point
+ * numbers.
+ */
+ public static function assertAllFloat($traversable) {
+ return static::assertAll('is_float', $traversable);
+ }
+
+ /**
+ * Asserts that all members are callable.
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members are callable.
+ */
+ public static function assertAllCallable($traversable) {
+ return static::assertAll('is_callable', $traversable);
+ }
+
+ /**
+ * Asserts that all members are not empty.
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members not empty.
+ */
+ public static function assertAllNotEmpty($traversable) {
+ if (static::assertTraversable($traversable)) {
+ foreach ($traversable as $member) {
+ if (empty($member)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Asserts all members are numeric data types or strings castable to such.
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members are numeric.
+ */
+ public static function assertAllNumeric($traversable) {
+ return static::assertAll('is_numeric', $traversable);
+ }
+
+ /**
+ * Asserts that all members are strings that contain the specified string.
+ *
+ * This runs faster than the regular expression equivalent.
+ *
+ * @param string $pattern
+ * The needle to find.
+ * @param mixed $traversable
+ * Variable to examine.
+ * @param bool $case_sensitive
+ * TRUE to use strstr(), FALSE to use stristr() which is case insensitive.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members are strings
+ * containing $pattern.
+ */
+ public static function assertAllMatch($pattern, $traversable, $case_sensitive = FALSE) {
+ if (static::assertTraversable($traversable)) {
+ if ($case_sensitive) {
+ foreach ($traversable as $member) {
+ if (!(is_string($member) && strstr($member, $pattern))) {
+ return FALSE;
+ }
+ }
+ }
+ else {
+ foreach ($traversable as $member) {
+ if (!(is_string($member) && stristr($member, $pattern))) {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+
+ /**
+ * Asserts that all members are strings matching a regular expression.
+ *
+ * @param string $pattern
+ * Regular expression string to find.
+ * @param mixed $traversable
+ * Variable to be examined.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members are strings
+ * matching $pattern.
+ */
+ public static function assertAllRegularExpressionMatch($pattern, $traversable) {
+ if (static::assertTraversable($traversable)) {
+ foreach ($traversable as $member) {
+ if (!is_string($member)) {
+ return FALSE;
+ }
+
+ if (!preg_match($pattern, $member)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Asserts that all members are objects.
+ *
+ * When testing if a collection is composed of objects those objects should
+ * be given a common interface to implement and the test should be written to
+ * search for just that interface. While this method will allow tests for
+ * just object status or for multiple classes and interfaces this was done to
+ * allow tests to be written for existing code without altering it. Only use
+ * this method in that manner when testing code from third party vendors.
+ *
+ * Here are some examples:
+ * @code
+ * // Just test all are objects, like a cache.
+ * assert('Drupal\\Component\\Assertion\\Inspector::assertAllObjects(
+ * $collection');
+ *
+ * // Test if traversable objects (arrays won't pass this)
+ * assert('Drupal\\Component\\Assertion\\Inspector::assertAllObjects(
+ * $collection', \'\\Traversable\');
+ *
+ * // Test for the Foo class or Bar\None interface
+ * assert('Drupal\\Component\\Assertion\\Inspector::assertAllObjects(
+ * $collection', \'\\Foo\', \'\\Bar\\None\'');
+ * @endcode
+ *
+ * @param mixed $traversable
+ * Variable to be examined.
+ * @param string ...
+ * Classes and interfaces to test objects against.
+ *
+ * @return bool
+ * TRUE if $traversable can be traversed and all members are objects with
+ * at least one of the listed classes or interfaces.
+ */
+ public static function assertAllObjects() {
+ $args = func_get_args();
+ $traversable = array_shift($args);
+
+ if (static::assertTraversable($traversable)) {
+ foreach ($traversable as $member) {
+ if (count($args) > 0) {
+ foreach ($args as $instance) {
+ if ($member instanceof $instance) {
+ // We're continuing to the next member on the outer loop.
+ // @see http://php.net/continue
+ continue 2;
+ }
+ }
+ return FALSE;
+ }
+ elseif (!is_object($member)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+}
diff --git a/core/tests/Drupal/Tests/Component/Assertion/InspectorTest.php b/core/tests/Drupal/Tests/Component/Assertion/InspectorTest.php
new file mode 100644
index 0000000..55b09d8
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Assertion/InspectorTest.php
@@ -0,0 +1,241 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\Tests\Component\InspectorTest.
+ */
+
+namespace Drupal\Tests\Component\Assertion;
+
+use PHPUnit_Framework_TestCase;
+use Drupal\Component\Assertion\Inspector;
+
+/**
+ * @coversDefaultClass \Drupal\Component\Assertion\Inspector
+ * @group Inspector
+ */
+class InspectorTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * Tests asserting argument is an array or traversable object.
+ *
+ * @covers ::assertTraversable
+ */
+ public function testAssertTraversable() {
+ $this->assertTrue(Inspector::assertTraversable([]));
+ $this->assertTrue(Inspector::assertTraversable(new \ArrayObject()));
+ $this->assertFalse(Inspector::assertTraversable(new \stdClass()));
+ $this->assertFalse(Inspector::assertTraversable('foo'));
+ }
+
+ /**
+ * Tests asserting all members are strings.
+ *
+ * @covers ::assertAllStrings
+ */
+ public function testAssertAllStrings() {
+ $this->assertTrue(Inspector::assertAllStrings([]));
+ $this->assertTrue(Inspector::assertAllStrings(['foo', 'bar']));
+ $this->assertFalse(Inspector::assertAllStrings('foo'));
+ $this->assertFalse(Inspector::assertAllStrings(['foo', new StringObject()]));
+ }
+
+ /**
+ * Tests asserting all members are strings or objects with __toString().
+ *
+ * @covers ::assertAllStringable
+ */
+ public function testAssertAllStringable() {
+ $this->assertTrue(Inspector::assertAllStringable([]));
+ $this->assertTrue(Inspector::assertAllStringable(['foo', 'bar']));
+ $this->assertFalse(Inspector::assertAllStringable('foo'));
+ $this->assertTrue(Inspector::assertAllStringable(['foo', new StringObject()]));
+ }
+
+ /**
+ * Tests asserting all members are arrays.
+ *
+ * @covers ::assertAllArrays
+ */
+ public function testAssertAllArrays() {
+ $this->assertTrue(Inspector::assertAllArrays([]));
+ $this->assertTrue(Inspector::assertAllArrays([[], []]));
+ $this->assertFalse(Inspector::assertAllArrays([[], 'foo']));
+ }
+
+ /**
+ * Tests asserting array is 0-indexed - the strict definition of array.
+ *
+ * @covers ::assertStrictArray
+ */
+ public function testAssertStrictArray() {
+ $this->assertTrue(Inspector::assertStrictArray([]));
+ $this->assertTrue(Inspector::assertStrictArray(['bar', 'foo']));
+ $this->assertFalse(Inspector::assertStrictArray(['foo' => 'bar', 'bar' => 'foo']));
+ }
+
+ /**
+ * Tests asserting all members are strict arrays.
+ *
+ * @covers ::assertAllStrictArrays
+ */
+ public function testAssertAllStrictArrays() {
+ $this->assertTrue(Inspector::assertAllStrictArrays([]));
+ $this->assertTrue(Inspector::assertAllStrictArrays([[], []]));
+ $this->assertFalse(Inspector::assertAllStrictArrays([['foo' => 'bar', 'bar' => 'foo']]));
+ }
+
+ /**
+ * Tests asserting all members have specified keys.
+ *
+ * @covers ::assertAllHaveKey
+ */
+ public function testAssertAllHaveKey() {
+ $this->assertTrue(Inspector::assertAllHaveKey([]));
+ $this->assertTrue(Inspector::assertAllHaveKey([['foo' => 'bar', 'bar' => 'foo']]));
+ $this->assertTrue(Inspector::assertAllHaveKey([['foo' => 'bar', 'bar' => 'foo']], 'foo'));
+ $this->assertTrue(Inspector::assertAllHaveKey([['foo' => 'bar', 'bar' => 'foo']], 'bar', 'foo'));
+ $this->assertFalse(Inspector::assertAllHaveKey([['foo' => 'bar', 'bar' => 'foo']], 'bar', 'foo', 'moo'));
+ }
+
+ /**
+ * Tests asserting all members are integers.
+ *
+ * @covers ::assertAllIntegers
+ */
+ public function testAssertAllIntegers() {
+ $this->assertTrue(Inspector::assertAllIntegers([]));
+ $this->assertTrue(Inspector::assertAllIntegers([1, 2, 3]));
+ $this->assertFalse(Inspector::assertAllIntegers([1, 2, 3.14]));
+ $this->assertFalse(Inspector::assertAllIntegers([1, '2', 3]));
+ }
+
+ /**
+ * Tests asserting all members are floating point variables.
+ *
+ * @covers ::assertAllFloat
+ */
+ public function testAssertAllFloat() {
+ $this->assertTrue(Inspector::assertAllFloat([]));
+ $this->assertTrue(Inspector::assertAllFloat([1.0, 2.1, 3.14]));
+ $this->assertFalse(Inspector::assertAllFloat([1, 2.1, 3.14]));
+ $this->assertFalse(Inspector::assertAllFloat([1.0, '2', 3]));
+ $this->assertFalse(Inspector::assertAllFloat(['Titanic']));
+ }
+
+ /**
+ * Tests asserting all members are callable.
+ *
+ * @covers ::assertAllCallable
+ */
+ public function testAllCallable() {
+ $this->assertTrue(Inspector::assertAllCallable([
+ 'strchr',
+ [$this, 'callMe'],
+ [__CLASS__, 'callMeStatic'],
+ function() {
+ return TRUE;
+ }
+ ]));
+
+ $this->assertFalse(Inspector::assertAllCallable([
+ 'strchr',
+ [$this, 'callMe'],
+ [__CLASS__, 'callMeStatic'],
+ function() {
+ return TRUE;
+ },
+ "I'm not callable"
+ ]));
+ }
+
+ /**
+ * Tests asserting all members are !empty().
+ *
+ * @covers ::assertAllNotEmpty
+ */
+ public function testAllNotEmpty() {
+ $this->assertTrue(Inspector::assertAllNotEmpty([1, 'two']));
+ $this->assertFalse(Inspector::assertAllNotEmpty(['']));
+ }
+
+ /**
+ * Tests asserting all arguments are numbers or strings castable to numbers.
+ *
+ * @covers ::assertAllNumeric
+ */
+ public function testAssertAllNumeric() {
+ $this->assertTrue(Inspector::assertAllNumeric([1, '2', 3.14]));
+ $this->assertFalse(Inspector::assertAllNumeric([1, 'two', 3.14]));
+ }
+
+ /**
+ * Tests asserting strstr() or stristr() match.
+ *
+ * @covers ::assertAllMatch
+ */
+ public function testAssertAllMatch() {
+ $this->assertTrue(Inspector::assertAllMatch('f', ['fee', 'fi', 'fo']));
+ $this->assertTrue(Inspector::assertAllMatch('F', ['fee', 'fi', 'fo']));
+ $this->assertTrue(Inspector::assertAllMatch('f', ['fee', 'fi', 'fo'], TRUE));
+ $this->assertFalse(Inspector::assertAllMatch('F', ['fee', 'fi', 'fo'], TRUE));
+ $this->assertFalse(Inspector::assertAllMatch('e', ['fee', 'fi', 'fo']));
+ $this->assertFalse(Inspector::assertAllMatch('1', [12]));
+ }
+
+ /**
+ * Tests asserting regular expression match.
+ *
+ * @covers ::assertAllRegularExpressionMatch
+ */
+ public function testAssertAllRegularExpressionMatch() {
+ $this->assertTrue(Inspector::assertAllRegularExpressionMatch('/f/i', ['fee', 'fi', 'fo']));
+ $this->assertTrue(Inspector::assertAllRegularExpressionMatch('/F/i', ['fee', 'fi', 'fo']));
+ $this->assertTrue(Inspector::assertAllRegularExpressionMatch('/f/', ['fee', 'fi', 'fo']));
+ $this->assertFalse(Inspector::assertAllRegularExpressionMatch('/F/', ['fee', 'fi', 'fo']));
+ $this->assertFalse(Inspector::assertAllRegularExpressionMatch('/e/', ['fee', 'fi', 'fo']));
+ $this->assertFalse(Inspector::assertAllRegularExpressionMatch('/1/', [12]));
+ }
+
+ /**
+ * Tests asserting all members are objects.
+ *
+ * @covers ::assertAllObjects
+ */
+ public function testAssertAllObjects() {
+ $this->assertTrue(Inspector::assertAllObjects([new \ArrayObject(), new \ArrayObject()]));
+ $this->assertFalse(Inspector::assertAllObjects([new \ArrayObject(), new \ArrayObject(), 'foo']));
+ $this->assertTrue(Inspector::assertAllObjects([new \ArrayObject(), new \ArrayObject()], '\\Traversable'));
+ $this->assertFalse(Inspector::assertAllObjects([new \ArrayObject(), new \ArrayObject(), 'foo'], '\\Traversable'));
+ $this->assertFalse(Inspector::assertAllObjects([new \ArrayObject(), new StringObject()], '\\Traversable'));
+ $this->assertTrue(Inspector::assertAllObjects([new \ArrayObject(), new StringObject()], '\\Traversable', '\\Drupal\\Tests\\Component\\Assertion\\StringObject'));
+ $this->assertFalse(Inspector::assertAllObjects([new \ArrayObject(), new StringObject(), new \stdClass()], '\\ArrayObject', '\\Drupal\\Tests\\Component\\Assertion\\StringObject'));
+ }
+
+ /**
+ * Test method referenced by ::testAllCallable().
+ */
+ public function callMe() {
+ return TRUE;
+ }
+
+ /**
+ * Test method referenced by ::testAllCallable().
+ */
+ public static function callMeStatic() {
+ return TRUE;
+ }
+
+}
+
+/**
+ * Quick class for testing for objects with __toString.
+ */
+class StringObject {
+ /**
+ * {@inheritdoc}
+ */
+ public function __toString() {
+ return 'foo';
+ }
+
+}
diff --git a/sites/example.settings.local.php b/sites/example.settings.local.php
index 56fed6f..34b4e19 100644
--- a/sites/example.settings.local.php
+++ b/sites/example.settings.local.php
@@ -12,6 +12,24 @@
*/
/**
+ * Assertions.
+ *
+ * The Drupal project primarily uses runtime assertions to enforce the
+ * expectations of the API by failing when incorrect calls are made by code
+ * under development.
+ *
+ * @see http://php.net/assert
+ * @see https://www.drupal.org/node/2492225
+ *
+ * If you are using PHP 7.0 it is strongly recommended that you set
+ * zend.assertions=1 in the PHP.ini file (It cannot be changed from .htaccess
+ * or runtime) on development machines and to 0 in production.
+ *
+ * @see https://wiki.php.net/rfc/expectations
+ */
+assert_options(ASSERT_ACTIVE, 1);
+
+/**
* Enable local development services.
*/
$settings['container_yamls'][] = DRUPAL_ROOT . '/sites/development.services.yml';