diff --git a/.htaccess b/.htaccess
index af418c4..bf725f2 100644
--- a/.htaccess
+++ b/.htaccess
@@ -28,13 +28,15 @@ 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.
+# changed at runtime. See sites/example.settings.local.php for more
+# information on assert.active.
 
 # 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 a8b13ca..9e1c3ef 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,45 @@
  */
 
 /**
+ * @defgroup php_assert PHP Runtime Assert Statements
+ * @{
+ * Use of the assert() statement in Drupal.
+ *
+ * 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
+ * tested with normal control structures and exception throws, not assert()
+ * statements).
+ *
+ * Since unit tests also use the term "assertion" to refer to test conditions
+ * the term "runtime assertion" will be used to refer specifically to uses of
+ * the assert() statement.
+ *
+ * The Drupal project has adopted runtime assertions to monitor interactions
+ * between the components, modules and themes that make up the project during
+ * development. They supplement unit tests by being able to check the validity
+ * of code that hasn't been written yet or that has no unit tests of its own.
+ * These checks slow the system down so they are disabled in production.
+ *
+ * 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.
+ *   See sites/example.settings.local.php for more information.
+ * - Always pass a single quoted string into assert() to minimize overhead
+ *   when assertions are turned off.
+ * - Assertions are parsed the same way as the eval() statement and therefore
+ *   have the same security implications as that statement. Use caution when
+ *   using them to work with any 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/Assertion.php b/core/lib/Drupal/Component/Assertion/Assertion.php
new file mode 100644
index 0000000..bc6385b
--- /dev/null
+++ b/core/lib/Drupal/Component/Assertion/Assertion.php
@@ -0,0 +1,368 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\Component\Assertion\Assertion.
+ */
+
+namespace Drupal\Component\Assertion;
+
+use Traversable;
+
+/**
+ * Collection of methods to assist the assert() statement.
+ *
+ * This is a static function collection for performing complicated runtime
+ * assertions.
+ *
+ * Example call:
+ * @code
+ *   assert('Drupal\\Component\\Assertion\\Assertion::assertAllStrings($array)');
+ * @endcode
+ *
+ * @ingroup php_assert
+ */
+class Assertion {
+
+  /**
+   * Assert argument can be traversed with foreach();
+   *
+   * @param mixed $traversable
+   *
+   * @return bool
+   */
+  public static function assertTraversable($traversable) {
+    return is_array($traversable) || $traversable instanceof Traversable;
+  }
+
+  /**
+   * Assert all members are strings.
+   *
+   * @param mixed $traversable
+   *
+   * @return bool
+   */
+  public static function assertAllStrings($traversable) {
+    if (static::assertTraversable($traversable)) {
+      foreach ($traversable as $member) {
+        if (!is_string($member)) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Assert all members are strings or objects with magic __toString() method.
+   *
+   * @param mixed $traversable
+   *
+   * @return bool
+   */
+  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;
+  }
+
+  /**
+   * Assert all members are associative arrays.
+   *
+   * This is the superset for PHP arrays. The other array tests are more
+   * specific than this.
+   *
+   * @param mixed $traversable
+   *
+   * @return bool
+   */
+  public static function assertAllAssociativeArrays($traversable) {
+     if (static::assertTraversable($traversable)) {
+      foreach ($traversable as $member) {
+        if (!is_array($member)) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Assert array is strict.
+   *
+   * A 'strict' array is an 0 indexed array in the classic sense found in
+   * programming languages other than PHP. We do not type hint on this function
+   * because we want to return false if the passed argument is not an array
+   * instead of halting program flow.
+   *
+   * @param mixed $array
+   *
+   * @return bool
+   */
+  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;
+  }
+
+  /**
+   * Assert all members are strict arrays.
+   *
+   * @param mixed $traversable
+   *
+   * @return bool
+   */
+  public static function assertAllStrictArrays($traversable) {
+    if (static::assertTraversable($traversable)) {
+      foreach ($traversable as $member) {
+        if (!static::assertStrictArray($member)) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Assert a key exists 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
+   *
+   * @param mixed $traversable
+   *
+   * @return bool
+   */
+  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;
+  }
+
+  /**
+   * Assert all members are integer values
+   *
+   * @param mixed $traversable
+   *
+   * @return bool
+   */
+  public static function assertAllIntegers($traversable) {
+     if (static::assertTraversable($traversable)) {
+      foreach ($traversable as $member) {
+        if (!is_int($member)) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Assert all members are float values.
+   *
+   * @param mixed $traversable
+   *
+   * @return bool
+   */
+  public static function assertAllFloat($traversable) {
+    if (static::assertTraversable($traversable)) {
+      foreach ($traversable as $member) {
+        if (!is_float($member)) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Assert all members are callable.
+   *
+   * @param mixed $traversable
+   *
+   * @return bool
+  */
+  public static function assertAllCallable($traversable) {
+    if (static::assertTraversable($traversable)) {
+      foreach ($traversable as $member) {
+        if (!is_callable($member)) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Assert all members are not empty.
+   *
+   * @param mixed $traversable
+   *
+   * @return bool
+   */
+  public static function assertAllNotEmpty($traversable) {
+    if (static::assertTraversable($traversable)) {
+      foreach ($traversable as $member) {
+        if (empty($member)) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Assert all members are numeric data types or strings castable to such.
+   *
+   * @param mixed $traversable
+   *
+   * @return bool
+   */
+  public static function assertAllNumeric($traversable) {
+    if (static::assertTraversable($traversable)) {
+      foreach ($traversable as $member) {
+        if (!is_numeric($member)) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Assert all members match a simple pattern and are strings.
+   *
+   * This runs faster than the regular expression equivalent.
+   *
+   * @param string $pattern
+   * @param mixed $traversable
+   * @param bool $case_sensitive
+   *
+   * @return bool
+   */
+  public static function assertAllMatch($pattern, $traversable, $case_sensitive = FALSE) {
+    if (static::assertTraversable($traversable)) {
+      foreach ($traversable as $member) {
+        if (!is_string($member)) {
+          return FALSE;
+        }
+
+        if ($case_sensitive) {
+          if (!strstr($member, $pattern)) {
+            return FALSE;
+          }
+        }
+        elseif (!stristr($member, $pattern)) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+
+  /**
+   * Assert all members match a regular expression.
+   *
+   * static::assertMatch() will be faster - use it when possible.
+   * Reminder - this function doesn't have a case sensitive parameter because
+   * case sensitivity is a flag you set as part of the regex pattern.
+   *
+   * @param regex $pattern
+   * @param mixed $traversable
+   *
+   * @return bool
+   */
+  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;
+  }
+
+  /**
+   * Assert all members are objects.
+   *
+   * You can overload this function. The first argument is required and is the
+   * collection of objects to test.  The second and subsequent arguments are
+   * the classes and interfaces to test for. The method returns TRUE if all
+   * members of the traversable are indeed objects, and if you pass in any
+   * classes and interfaces the method will return TRUE if the object has
+   * at least one of those interfaces.
+   *
+   * Note that if it is important enough to your code that a collection be
+   * tested to be a collection of objects then it is important enough to give
+   * all of those objects a common interface and test for just that interface.
+   * This method is written to allow for other tests to be written to minimize
+   * potential disruption, but they should be used sparingly if at all.
+   */
+  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/lib/Drupal/Component/Assertion/AssertionException.php b/core/lib/Drupal/Component/Assertion/AssertionException.php
new file mode 100644
index 0000000..085e4b3
--- /dev/null
+++ b/core/lib/Drupal/Component/Assertion/AssertionException.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * @file
+ * Contains Drupal\Component\Assertion\AssertionException.
+ */
+
+namespace Drupal\Component\Assertion;
+
+/**
+ * Exception to be thrown when a runtime assertion fails.
+ *
+ * Assertion-aware tests (those which implement PHPUnitTestingTrait or
+ * AssertionTestingTrait) normally allow code to continue in spite of a runtime
+ * assertion failure to see if the code remains (relatively) stable despite the
+ * failure. However some runtime assertions will be followed by a fatal error
+ * when they fail. Unit tests for them must throw an exception to end the test
+ * immediately.
+ *
+ * @see BaseTestingTrait
+ * @ingroup php_assert
+ */
+class AssertionException extends \Exception {}
diff --git a/core/lib/Drupal/Component/Assertion/BaseAssertionTestingTrait.php b/core/lib/Drupal/Component/Assertion/BaseAssertionTestingTrait.php
new file mode 100644
index 0000000..fd8048f
--- /dev/null
+++ b/core/lib/Drupal/Component/Assertion/BaseAssertionTestingTrait.php
@@ -0,0 +1,155 @@
+<?php
+/**
+ * @file
+ * Contains Drupal\Component\Assertion\BaseAssertionTestingTrait.
+ */
+
+namespace Drupal\Component\Assertion;
+
+/**
+ * Methods for unit testing code which uses the PHP assert() function.
+ *
+ * Before we begin note the following - the term "assertion" is used throughout
+ * PHPUnit and Simpletest's documentation to refer to the conditions checked
+ * by their test classes.  The term "runtime assertion" will be used to refer
+ * to assertions made by the assert() statement.
+ *
+ * Now, by default both PHPUnit and Simpletest will stop when a runtime
+ * assertion fails without any special configuration. This will be sufficient
+ * for the vast majority of runtime assertions.
+ *
+ * When you add a runtime assertion that is checking anything more complex
+ * than a variable type or calling a helper method in
+ * \Drupal\Component\Assertion\Assertion you should write a unit test for that
+ * runtime assertion. This trait contains helper methods for such tests.
+ *
+ * This trait establishes an assert() callback that logs assert() statement
+ * failures as they occur and then it allows the code to continue executing as
+ * it would in production with assert() statements turned off. Tests
+ * implementing this trait check this log to see if the expected assert
+ * failures did indeed occur and that no others occurred.
+ *
+ * Some runtime assertions check a condition whose failure leads to a fatal
+ * error. When testing the failure of these runtime assertions set the
+ * dieOnRaise flag to TRUE to cause a
+ * Drupal\Component\Assertion\AssertionException to be thrown.
+ *
+ * To use this trait the following setup and teardown methods must be added
+ * to the implementing class.
+ *
+ * @code
+ * public function setUp() {
+ *   parent::setUp();
+ *   $this->startAssertionHandling();
+ * }
+ *
+ * public function tearDown() {
+ *   $this->stopAssertionHandling();
+ *   parent::tearDown();
+ * }
+ * @endcode
+ *
+ * Note that the special handling of runtime assertions is to be in effect
+ * only while the test is running, not during its actual setup or teardown. If
+ * a runtime assertion fails during setup or teardown then an E_WARNING will
+ * be raised and the test will halt.
+ *
+ * @ingroup php_assert
+ */
+trait BaseAssertionTestingTrait {
+
+  /**
+   * Error string to output if the test writer doesn't use a string argument.
+   *
+   * @var string
+   */
+  protected $assertionsMustBeStrings = 'The first argument to assert()
+    should always be a string even though PHP permits other argument types for
+    two reasons: First, those arguments will increase overhead even when
+    runtime assertions are turned off. Second, assertion-aware unit tests
+    require a code string in order to label the runtime assertion.';
+
+  /**
+   * Flag to throw an exception immediately on failure.
+   *
+   * @var bool
+   */
+  protected $dieOnRaise = FALSE;
+
+  /**
+   * Collection of captured assertions.
+   *
+   * @var String[]
+   */
+  protected $assertionsRaised = [];
+
+  /**
+   * Callback handler for assert() failures during testing.
+   *
+   * Note - despite the name this is not an assert condition you call during
+   * a unit test!
+   */
+  public function assertCallbackHandle($file, $line, $code, $message = '') {
+
+    // We print out this warning during test development, and since the
+    // automated tests run in strict mode it will cause a test failure.
+    if (!$code) {
+      print ($this->assertionsMustBeStrings);
+    }
+
+    if ($this->dieOnRaise) {
+      throw new AssertionException($code . ' ' . $message);
+    }
+
+    $this->assertionsRaised[] = $code;
+    return TRUE;
+  }
+
+  /**
+   * Start assertion handling for the test.
+   *
+   * Call this from setUp()
+   */
+  protected function startAssertionHandling() {
+    assert_options(ASSERT_WARNING, FALSE);
+    assert_options(ASSERT_BAIL, FALSE);
+    assert_options(ASSERT_CALLBACK, [$this, 'assertCallbackHandle']);
+    $this->assertionsRaised = [];
+    return FALSE;
+  }
+
+  /**
+   * Suspend assertion handling.
+   */
+  protected function suspendAssertionHandling() {
+    assert_options(ASSERT_WARNING, TRUE);
+    assert_options(ASSERT_CALLBACK, NULL);
+    $this->assertionsRaised = [];
+  }
+
+  /**
+   * Cease handling assertions and clear the way for the next test.
+   *
+   * Call this from tearDown()
+   */
+  protected function stopAssertionHandling() {
+    $this->assertAssertionNotRaised();
+    $this->suspendAssertionHandling();
+    $this->dieOnRaise = FALSE;
+  }
+
+  /**
+   * Check if the runtime assertions specified where failed.
+   *
+   * This function can be overloaded. Runtime assertions should be passed in
+   * the order they are expected to occur using their evaluation string as a
+   * label. After being accounted for the assertion count is reset.
+   */
+  abstract protected function assertAssertionsRaised();
+
+  /**
+   * Insure no runtime assertions where thrown.
+   */
+  abstract protected function assertAssertionNotRaised();
+
+}
diff --git a/core/lib/Drupal/Component/Assertion/PHPUnitTestingTrait.php b/core/lib/Drupal/Component/Assertion/PHPUnitTestingTrait.php
new file mode 100644
index 0000000..d0963b9
--- /dev/null
+++ b/core/lib/Drupal/Component/Assertion/PHPUnitTestingTrait.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * @file
+ * Contains Drupal\Component\Assertion\PHPUnitTestingTrait.
+ */
+
+namespace Drupal\Component\Assertion;
+
+
+/**
+ * Methods for testing the internal PHP assert function in PHPUnit.
+ *
+ * @ingroup php_assert
+ */
+trait PHPUnitTestingTrait {
+  use BaseAssertionTestingTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function assertAssertionsRaised() {
+    $this->assertEquals(func_get_args(), $this->assertionsRaised);
+    $this->assertionsRaised = [];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function assertAssertionNotRaised() {
+    $this->assertEmpty($this->assertionsRaised);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Cache/ApcuBackend.php b/core/lib/Drupal/Core/Cache/ApcuBackend.php
index 9bac79e..bfc1913 100644
--- a/core/lib/Drupal/Core/Cache/ApcuBackend.php
+++ b/core/lib/Drupal/Core/Cache/ApcuBackend.php
@@ -53,6 +53,9 @@ class ApcuBackend implements CacheBackendInterface {
    *   The cache tags checksum provider.
    */
   public function __construct($bin, $site_prefix, CacheTagsChecksumInterface $checksum_provider) {
+    assert('is_string($bin)');
+    assert('is_string($site_prefix)');
+
     $this->bin = $bin;
     $this->sitePrefix = $site_prefix;
     $this->checksumProvider = $checksum_provider;
@@ -69,6 +72,7 @@ public function __construct($bin, $site_prefix, CacheTagsChecksumInterface $chec
    *   The APCu key for the cache item ID.
    */
   protected function getApcuKey($cid) {
+    assert('is_string($cid)');
     return $this->binPrefix . $cid;
   }
 
@@ -76,6 +80,7 @@ protected function getApcuKey($cid) {
    * {@inheritdoc}
    */
   public function get($cid, $allow_invalid = FALSE) {
+    assert('is_string($cid)');
     $cache = apc_fetch($this->getApcuKey($cid));
     return $this->prepareItem($cache, $allow_invalid);
   }
@@ -84,6 +89,7 @@ public function get($cid, $allow_invalid = FALSE) {
    * {@inheritdoc}
    */
   public function getMultiple(&$cids, $allow_invalid = FALSE) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cids)');
     // Translate the requested cache item IDs to APCu keys.
     $map = array();
     foreach ($cids as $cid) {
@@ -166,7 +172,8 @@ protected function prepareItem($cache, $allow_invalid) {
    * {@inheritdoc}
    */
   public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) {
-    Cache::validateTags($tags);
+    assert('is_string($cid)');
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($tags)');
     $tags = array_unique($tags);
     $cache = new \stdClass();
     $cache->cid = $cid;
@@ -201,6 +208,7 @@ public function setMultiple(array $items = array()) {
    * {@inheritdoc}
    */
   public function delete($cid) {
+    assert('is_string($cid)');
     apc_delete($this->getApcuKey($cid));
   }
 
@@ -208,6 +216,7 @@ public function delete($cid) {
    * {@inheritdoc}
    */
   public function deleteMultiple(array $cids) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cids)');
     apc_delete(array_map(array($this, 'getApcuKey'), $cids));
   }
 
@@ -236,6 +245,7 @@ public function removeBin() {
    * {@inheritdoc}
    */
   public function invalidate($cid) {
+    assert('is_string($cid)');
     $this->invalidateMultiple(array($cid));
   }
 
@@ -243,6 +253,7 @@ public function invalidate($cid) {
    * {@inheritdoc}
    */
   public function invalidateMultiple(array $cids) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cids)');
     foreach ($this->getMultiple($cids) as $cache) {
       $this->set($cache->cid, $cache, REQUEST_TIME - 1);
     }
diff --git a/core/lib/Drupal/Core/Cache/Cache.php b/core/lib/Drupal/Core/Cache/Cache.php
index d149592..cb1dabc 100644
--- a/core/lib/Drupal/Core/Cache/Cache.php
+++ b/core/lib/Drupal/Core/Cache/Cache.php
@@ -37,7 +37,7 @@ public static function mergeContexts() {
       $cache_contexts = array_merge($cache_contexts, $contexts);
     }
     $cache_contexts = array_unique($cache_contexts);
-    \Drupal::service('cache_contexts_manager')->validateTokens($cache_contexts);
+    assert('\\Drupal::service(\'cache_contexts_manager\')->assertValidTokens($cache_contexts)');
     sort($cache_contexts);
     return $cache_contexts;
   }
@@ -66,7 +66,7 @@ public static function mergeTags() {
       $cache_tags = array_merge($cache_tags, $tags);
     }
     $cache_tags = array_unique($cache_tags);
-    static::validateTags($cache_tags);
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cache_tags)');
     sort($cache_tags);
     return $cache_tags;
   }
@@ -110,6 +110,8 @@ public static function mergeMaxAges() {
    *   An array of cache tags.
    *
    * @throws \LogicException
+   *
+   * @deprecated use assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($tags)');
    */
   public static function validateTags(array $tags) {
     if (empty($tags)) {
@@ -139,10 +141,14 @@ public static function validateTags(array $tags) {
    *   An array of cache tags.
    */
   public static function buildTags($prefix, array $suffixes, $glue = ':') {
+    assert('is_string($prefix)');
+    assert('is_string($glue)');
+
     $tags = [];
     foreach ($suffixes as $suffix) {
       $tags[] = $prefix . $glue . $suffix;
     }
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($tags)');
     return $tags;
   }
 
@@ -153,6 +159,7 @@ public static function buildTags($prefix, array $suffixes, $glue = ':') {
    *   The list of tags to invalidate cache items for.
    */
   public static function invalidateTags(array $tags) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($tags)');
     \Drupal::service('cache_tags.invalidator')->invalidateTags($tags);
   }
 
diff --git a/core/lib/Drupal/Core/Cache/CacheCollector.php b/core/lib/Drupal/Core/Cache/CacheCollector.php
index a6d8ab5..3622718 100644
--- a/core/lib/Drupal/Core/Cache/CacheCollector.php
+++ b/core/lib/Drupal/Core/Cache/CacheCollector.php
@@ -115,7 +115,7 @@
    *   (optional) The tags to specify for the cache item.
    */
   public function __construct($cid, CacheBackendInterface $cache, LockBackendInterface $lock, array $tags = array()) {
-    Cache::validateTags($tags);
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($tags)');
     $this->cid = $cid;
     $this->cache = $cache;
     $this->tags = $tags;
@@ -135,6 +135,7 @@ protected function getCid() {
    * {@inheritdoc}
    */
   public function has($key) {
+    assert('is_string($key)');
     // Make sure the value is loaded.
     $this->get($key);
     return isset($this->storage[$key]) || array_key_exists($key, $this->storage);
@@ -144,6 +145,7 @@ public function has($key) {
    * {@inheritdoc}
    */
   public function get($key) {
+    assert('is_string($key)');
     $this->lazyLoadCache();
     if (isset($this->storage[$key]) || array_key_exists($key, $this->storage)) {
       return $this->storage[$key];
@@ -163,6 +165,8 @@ public function get($key) {
    * this behavior, for example by adding a call to persist().
    */
   public function set($key, $value) {
+    assert('is_string($key)');
+
     $this->lazyLoadCache();
     $this->storage[$key] = $value;
     // The key might have been marked for deletion.
@@ -175,6 +179,8 @@ public function set($key, $value) {
    * {@inheritdoc}
    */
   public function delete($key) {
+    assert('is_string($key)');
+
     $this->lazyLoadCache();
     unset($this->storage[$key]);
     $this->keysToRemove[$key] = $key;
diff --git a/core/lib/Drupal/Core/Cache/CacheTagsInvalidator.php b/core/lib/Drupal/Core/Cache/CacheTagsInvalidator.php
index 64a8eb0..f342613 100644
--- a/core/lib/Drupal/Core/Cache/CacheTagsInvalidator.php
+++ b/core/lib/Drupal/Core/Cache/CacheTagsInvalidator.php
@@ -27,8 +27,7 @@ class CacheTagsInvalidator implements CacheTagsInvalidatorInterface {
    * {@inheritdoc}
    */
   public function invalidateTags(array $tags) {
-    // Validate the tags.
-    Cache::validateTags($tags);
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($tags)');
 
     // Notify all added cache tags invalidators.
     foreach ($this->invalidators as $invalidator) {
diff --git a/core/lib/Drupal/Core/Cache/Context/CacheContextsManager.php b/core/lib/Drupal/Core/Cache/Context/CacheContextsManager.php
index 27b012a..58c0b60 100644
--- a/core/lib/Drupal/Core/Cache/Context/CacheContextsManager.php
+++ b/core/lib/Drupal/Core/Cache/Context/CacheContextsManager.php
@@ -148,6 +148,8 @@ public function convertTokensToKeys(array $context_tokens) {
    *   A representative subset of the given set of cache context tokens..
    */
   public function optimizeTokens(array $context_tokens) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($context_tokens)');
+
     $optimized_content_tokens = [];
     foreach ($context_tokens as $context_token) {
       // Context tokens without:
@@ -178,6 +180,8 @@ public function optimizeTokens(array $context_tokens) {
         }
       }
     }
+
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($optimized_content_tokens)');
     return $optimized_content_tokens;
   }
 
@@ -209,6 +213,8 @@ protected function getService($context_id) {
    *     there is no parameter.
    */
   public static function parseTokens(array $context_tokens) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($context_tokens)');
+
     $contexts_with_parameters = [];
     foreach ($context_tokens as $context) {
       $context_id = $context;
@@ -231,6 +237,9 @@ public static function parseTokens(array $context_tokens) {
    *
    * @throws \LogicException
    *
+   * @deprecated Direct invocation of this method is deprecated.
+   *   Use the assert statement to invoke ::assertValidTokens in this class.
+   *
    * @see \Drupal\Core\Cache\Context\CacheContextsManager::parseTokens()
    */
   public function validateTokens(array $context_tokens = []) {
@@ -271,4 +280,19 @@ public function validateTokens(array $context_tokens = []) {
     }
   }
 
+  /**
+   * Assert statement wrapper for ::validateTokens()
+   *
+   * @param string[] $context_tokens
+   *   An array of cache context tokens.
+   */
+  public function assertValidTokens(array $context_tokens = []) {
+    try {
+      $this->validateTokens($context_tokens);
+    } catch ( \LogicException $e) {
+      return FALSE;
+    }
+    return TRUE;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index 49e830b..28d84f4 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -52,6 +52,8 @@ class DatabaseBackend implements CacheBackendInterface {
    *   The cache bin for which the object is created.
    */
   public function __construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, $bin) {
+    assert('is_string($bin)');
+
     // All cache tables should be prefixed with 'cache_'.
     $bin = 'cache_' . $bin;
 
@@ -64,6 +66,7 @@ public function __construct(Connection $connection, CacheTagsChecksumInterface $
    * Implements Drupal\Core\Cache\CacheBackendInterface::get().
    */
   public function get($cid, $allow_invalid = FALSE) {
+    assert('is_string($cid)');
     $cids = array($cid);
     $cache = $this->getMultiple($cids, $allow_invalid);
     return reset($cache);
@@ -73,6 +76,7 @@ public function get($cid, $allow_invalid = FALSE) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple().
    */
   public function getMultiple(&$cids, $allow_invalid = FALSE) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cids)');
     $cid_mapping = array();
     foreach ($cids as $cid) {
       $cid_mapping[$this->normalizeCid($cid)] = $cid;
@@ -120,6 +124,7 @@ public function getMultiple(&$cids, $allow_invalid = FALSE) {
    *   whether the item is valid, or FALSE if there is no valid item to load.
    */
   protected function prepareItem($cache, $allow_invalid) {
+    assert('is_object($cache)');
     if (!isset($cache->data)) {
       return FALSE;
     }
@@ -150,7 +155,8 @@ protected function prepareItem($cache, $allow_invalid) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::set().
    */
   public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) {
-    Cache::validateTags($tags);
+    assert('is_string($cid)');
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($tags)');
     $tags = array_unique($tags);
     // Sort the cache tags so that they are stored consistently in the database.
     sort($tags);
@@ -210,7 +216,7 @@ public function setMultiple(array $items) {
         'tags' => array(),
       );
 
-      Cache::validateTags($item['tags']);
+      assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($item[\'tags\'])');
       $item['tags'] = array_unique($item['tags']);
       // Sort the cache tags so that they are stored consistently in the DB.
       sort($item['tags']);
@@ -315,6 +321,7 @@ public function deleteAll() {
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidate().
    */
   public function invalidate($cid) {
+    assert('is_string($cid)');
     $this->invalidateMultiple(array($cid));
   }
 
@@ -322,6 +329,7 @@ public function invalidate($cid) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple().
    */
   public function invalidateMultiple(array $cids) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cids)');
     $cids = array_values(array_map(array($this, 'normalizeCid'), $cids));
     try {
       // Update in chunks when a large array is passed.
diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php
index d9bad8d..a479927 100644
--- a/core/lib/Drupal/Core/Cache/MemoryBackend.php
+++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php
@@ -37,6 +37,8 @@ public function __construct($bin) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::get().
    */
   public function get($cid, $allow_invalid = FALSE) {
+    assert('is_string($cid)');
+
     if (isset($this->cache[$cid])) {
       return $this->prepareItem($this->cache[$cid], $allow_invalid);
     }
@@ -49,6 +51,8 @@ public function get($cid, $allow_invalid = FALSE) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple().
    */
   public function getMultiple(&$cids, $allow_invalid = FALSE) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cids)');
+
     $ret = array();
 
     $items = array_intersect_key($this->cache, array_flip($cids));
@@ -107,7 +111,9 @@ protected function prepareItem($cache, $allow_invalid) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::set().
    */
   public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) {
-    Cache::validateTags($tags);
+    assert('is_string($cid)');
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($tags)');
+
     $tags = array_unique($tags);
     // Sort the cache tags so that they are stored consistently in the database.
     sort($tags);
@@ -140,6 +146,7 @@ public function delete($cid) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::deleteMultiple().
    */
   public function deleteMultiple(array $cids) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cids)');
     $this->cache = array_diff_key($this->cache, array_flip($cids));
   }
 
@@ -154,6 +161,8 @@ public function deleteAll() {
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidate().
    */
   public function invalidate($cid) {
+    assert('is_string($cid)');
+
     if (isset($this->cache[$cid])) {
       $this->cache[$cid]->expire = $this->getRequestTime() - 1;
     }
@@ -163,6 +172,8 @@ public function invalidate($cid) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple().
    */
   public function invalidateMultiple(array $cids) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cids)');
+
     foreach ($cids as $cid) {
       $this->cache[$cid]->expire = $this->getRequestTime() - 1;
     }
@@ -172,6 +183,7 @@ public function invalidateMultiple(array $cids) {
    * {@inheritdoc}
    */
   public function invalidateTags(array $tags) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($tags)');
     foreach ($this->cache as $cid => $item) {
       if (array_intersect($tags, $item->tags)) {
         $this->cache[$cid]->expire = $this->getRequestTime() - 1;
diff --git a/core/lib/Drupal/Core/Cache/PhpBackend.php b/core/lib/Drupal/Core/Cache/PhpBackend.php
index 761e394..19ec3f8 100644
--- a/core/lib/Drupal/Core/Cache/PhpBackend.php
+++ b/core/lib/Drupal/Core/Cache/PhpBackend.php
@@ -51,6 +51,8 @@ class PhpBackend implements CacheBackendInterface {
    *   The cache tags checksum provider.
    */
   public function __construct($bin, CacheTagsChecksumInterface $checksum_provider) {
+    assert('is_string($bin)');
+
     $this->bin = 'cache_' . $bin;
     $this->checksumProvider = $checksum_provider;
   }
@@ -59,6 +61,7 @@ public function __construct($bin, CacheTagsChecksumInterface $checksum_provider)
    * {@inheritdoc}
    */
   public function get($cid, $allow_invalid = FALSE) {
+    assert('is_string($cid)');
     return $this->getByHash($this->normalizeCid($cid), $allow_invalid);
   }
 
@@ -74,6 +77,8 @@ public function get($cid, $allow_invalid = FALSE) {
    * @return bool|mixed
    */
   protected function getByHash($cidhash, $allow_invalid = FALSE) {
+    assert('is_string($cidhash)');
+
     if ($file = $this->storage()->getFullPath($cidhash)) {
       $cache = @include $file;
     }
@@ -96,6 +101,7 @@ public function setMultiple(array $items) {
    * {@inheritdoc}
    */
   public function getMultiple(&$cids, $allow_invalid = FALSE) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cids)');
     $ret = array();
 
     foreach ($cids as $cid) {
@@ -148,7 +154,9 @@ protected function prepareItem($cache, $allow_invalid) {
    * {@inheritdoc}
    */
   public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) {
-    Cache::validateTags($tags);
+    assert('is_string($cid)');
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($tags)');
+
     $item = (object) array(
       'cid' => $cid,
       'data' => $data,
@@ -164,6 +172,8 @@ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array
    * {@inheritdoc}
    */
   public function delete($cid) {
+    assert('is_string($cid)');
+
     $this->storage()->delete($this->normalizeCid($cid));
   }
 
@@ -171,6 +181,8 @@ public function delete($cid) {
    * {@inheritdoc}
    */
   public function deleteMultiple(array $cids) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cids)');
+
     foreach ($cids as $cid) {
       $this->delete($cid);
     }
@@ -187,6 +199,8 @@ public function deleteAll() {
    * {@inheritdoc}
    */
   public function invalidate($cid) {
+    assert('is_string($cid)');
+
     $this->invalidatebyHash($this->normalizeCid($cid));
   }
 
@@ -207,6 +221,8 @@ protected function invalidatebyHash($cidhash) {
    * {@inheritdoc}
    */
   public function invalidateMultiple(array $cids) {
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cids)');
+
     foreach ($cids as $cid) {
       $this->invalidate($cid);
     }
diff --git a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
index ceabcd9..fd61ec1 100644
--- a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
+++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
@@ -126,6 +126,9 @@ class DefaultPluginManager extends PluginManagerBase implements PluginManagerInt
    *   Defaults to 'Drupal\Component\Annotation\Plugin'.
    */
   public function __construct($subdir, \Traversable $namespaces, ModuleHandlerInterface $module_handler, $plugin_interface = NULL, $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') {
+    assert('is_string($subdir) || is_bool($subdir)');
+    assert('is_null($plugin_interface) || interface_exists($plugin_interface)');
+
     $this->subdir = $subdir;
     $this->namespaces = $namespaces;
     $this->pluginDefinitionAnnotationName = $plugin_definition_annotation_name;
@@ -154,7 +157,9 @@ public function __construct($subdir, \Traversable $namespaces, ModuleHandlerInte
    *   definitions should be cleared along with other, related cache entries.
    */
   public function setCacheBackend(CacheBackendInterface $cache_backend, $cache_key, array $cache_tags = array()) {
-    Cache::validateTags($cache_tags);
+    assert('is_string($cache_key)');
+    assert('\\Drupal\\Component\\Assertion\\Assertion::assertAllStrings($cache_tags)');
+
     $this->cacheBackend = $cache_backend;
     $this->cacheKey = $cache_key;
     $this->cacheTags = $cache_tags;
@@ -168,6 +173,7 @@ public function setCacheBackend(CacheBackendInterface $cache_backend, $cache_key
    *   hook_mymodule_data_alter() pass in "mymodule_data".
    */
   protected function alterInfo($alter_hook) {
+    assert('is_string($alter_hook)');
     $this->alterHook = $alter_hook;
   }
 
@@ -212,6 +218,7 @@ protected function getCachedDefinitions() {
     if (!isset($this->definitions) && $cache = $this->cacheGet($this->cacheKey)) {
       $this->definitions = $cache->data;
     }
+    assert('is_null($this->definitions) || is_array($this->definitions)');
     return $this->definitions;
   }
 
@@ -221,7 +228,7 @@ protected function getCachedDefinitions() {
    * @param array $definitions
    *   List of definitions to store in cache.
    */
-  protected function setCachedDefinitions($definitions) {
+  protected function setCachedDefinitions(array $definitions) {
     $this->cacheSet($this->cacheKey, $definitions, Cache::PERMANENT, $this->cacheTags);
     $this->definitions = $definitions;
   }
@@ -318,6 +325,7 @@ protected function findDefinitions() {
         unset($definitions[$plugin_id]);
       }
     }
+    assert('is_array($definitions)');
     return $definitions;
   }
 
diff --git a/core/modules/language/tests/src/Unit/LanguageNegotiationUrlTest.php b/core/modules/language/tests/src/Unit/LanguageNegotiationUrlTest.php
index 76d72b5..1a1e4cc 100644
--- a/core/modules/language/tests/src/Unit/LanguageNegotiationUrlTest.php
+++ b/core/modules/language/tests/src/Unit/LanguageNegotiationUrlTest.php
@@ -60,9 +60,12 @@ protected function setUp() {
     $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
       ->disableOriginalConstructor()
       ->getMock();
+    $cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
     $container = new ContainerBuilder();
     $container->set('cache_contexts_manager', $cache_contexts_manager);
+
     \Drupal::setContainer($container);
+
   }
 
   /**
diff --git a/core/modules/simpletest/src/AssertionTestingTrait.php b/core/modules/simpletest/src/AssertionTestingTrait.php
new file mode 100644
index 0000000..b7a298c
--- /dev/null
+++ b/core/modules/simpletest/src/AssertionTestingTrait.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\simpletest\AssertionTestingTrait.
+ */
+
+namespace Drupal\simpletest;
+
+use Drupal\Component\Assertion\BaseAssertionTestingTrait;
+
+/**
+ * Methods for testing the internal PHP assert function in Simpletest.
+ *
+ * @ingroup php_assert
+ */
+trait AssertionTestingTrait {
+  use BaseAssertionTestingTrait;
+  /**
+   * {@inheritdoc}
+   */
+  protected function assertAssertionsRaised() {
+    $this->assertIdentical(func_get_args(), $this->assertionsRaised, 'Expected Assertions Raised.');
+    $this->assertionsRaised = [];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function assertAssertionNotRaised() {
+    $this->assertTrue(count($this->assertionsRaised) === 0, 'No Assertions Raised');
+  }
+
+}
diff --git a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
index cc0d9df..a9efa88 100644
--- a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
+++ b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
@@ -10,6 +10,8 @@
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\simpletest\KernelTestBase;
+use Drupal\simpletest\AssertionTestingTrait;
+use Drupal\Component\Assertion\AssertionException;
 
 /**
  * Tests any cache backend.
@@ -22,6 +24,7 @@
  *   For a full working implementation.
  */
 abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
+  use AssertionTestingTrait;
 
   /**
    * Array of objects implementing Drupal\Core\Cache\CacheBackendInterface.
@@ -107,6 +110,7 @@ protected function getCacheBackend($bin = null) {
   }
 
   protected function setUp() {
+    $this->startAssertionHandling();
     $this->cachebackends = array();
     $this->defaultValue = $this->randomMachineName(10);
 
@@ -116,6 +120,8 @@ protected function setUp() {
   }
 
   protected function tearDown() {
+    $this->stopAssertionHandling();
+
     // Destruct the registered backend, each test will get a fresh instance,
     // properly emptying it here ensure that on persistent data backends they
     // will come up empty the next test.
@@ -219,12 +225,14 @@ public function testSetGet() {
     $this->assertFalse($backend->get('test8'));
 
     // Calling ::set() with invalid cache tags.
+    $this->dieOnRaise = TRUE;
     try {
       $backend->set('exception_test', 'value', Cache::PERMANENT, ['node' => [3, 5, 7]]);
-      $this->fail('::set() was called with invalid cache tags, no exception was thrown.');
+      $this->fail('::set() was called with invalid cache tags, no assertion raised.');
     }
-    catch (\LogicException $e) {
-      $this->pass('::set() was called with invalid cache tags, an exception was thrown.');
+    catch (AssertionException $e) {
+      $this->pass('::set() was called with invalid cache tags, an assertion was raised.');
+      $this->dieOnRaise = FALSE;
     }
   }
 
@@ -413,6 +421,7 @@ public function testSetMultiple() {
     $this->assertEqual($cached['cid_5']->data, $items['cid_5']['data'], 'New cache item set correctly.');
 
     // Calling ::setMultiple() with invalid cache tags.
+    $this->dieOnRaise = TRUE;
     try {
       $items = [
         'exception_test_1' => array('data' => 1, 'tags' => []),
@@ -420,10 +429,11 @@ public function testSetMultiple() {
         'exception_test_3' => array('data' => 3, 'tags' => ['node' => [3, 5, 7]]),
       ];
       $backend->setMultiple($items);
-      $this->fail('::setMultiple() was called with invalid cache tags, no exception was thrown.');
+      $this->fail('::setMultiple() was called with invalid cache tags, no assertion was raised.');
     }
-    catch (\LogicException $e) {
-      $this->pass('::setMultiple() was called with invalid cache tags, an exception was thrown.');
+    catch (AssertionException $e) {
+      $this->pass('::setMultiple() was called with invalid cache tags, an assertion was raised.');
+      $this->dieOnRaise = FALSE;
     }
   }
 
diff --git a/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php b/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php
index 5e7f2a2..2322bc3 100644
--- a/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php
+++ b/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php
@@ -47,6 +47,7 @@ protected function setUp() {
     $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
       ->disableOriginalConstructor()
       ->getMock();
+    $cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
     $container = new ContainerBuilder();
     $container->set('cache_contexts_manager', $cache_contexts_manager);
     \Drupal::setContainer($container);
diff --git a/core/tests/Drupal/Tests/Component/Assertion/AssertionTest.php b/core/tests/Drupal/Tests/Component/Assertion/AssertionTest.php
new file mode 100644
index 0000000..2f5ec7a
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Assertion/AssertionTest.php
@@ -0,0 +1,216 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\Tests\Component\AssertionTest.
+ */
+
+namespace Drupal\Tests\Component\Assertion;
+
+use ArrayObject;
+use stdClass;
+use PHPUnit_Framework_TestCase;
+use Drupal\Component\Assertion\Assertion;
+
+/**
+ * Test the static Assertion assisting Library.
+ *
+ * @coversDefaultClass \Drupal\Component\Assertion\Assertion
+ *
+ * @group Assertion
+ */
+class AssertionTest extends PHPUnit_Framework_TestCase {
+
+  /**
+   * @covers ::assertTraversable
+   */
+  public function testAssertTraversable() {
+    $this->assertTrue(Assertion::assertTraversable([]));
+    $this->assertTrue(Assertion::assertTraversable(new ArrayObject()));
+    $this->assertFalse(Assertion::assertTraversable(new stdClass()));
+    $this->assertFalse(Assertion::assertTraversable('foo'));
+  }
+
+  /**
+   * @covers ::assertAllStrings
+   */
+  public function testAssertAllStrings() {
+    $this->assertTrue(Assertion::assertAllStrings([]));
+    $this->assertTrue(Assertion::assertAllStrings(['foo','bar']));
+    $this->assertFalse(Assertion::assertAllStrings('foo'));
+    $this->assertFalse(Assertion::assertAllStrings(['foo', new StringObject()]));
+  }
+
+  /**
+   * @covers ::assertAllStringable
+   */
+  public function testAssertAllStringable() {
+    $this->assertTrue(Assertion::assertAllStringable([]));
+    $this->assertTrue(Assertion::assertAllStringable(['foo','bar']));
+    $this->assertFalse(Assertion::assertAllStringable('foo'));
+    $this->assertTrue(Assertion::assertAllStringable(['foo', new StringObject()]));
+  }
+
+  /**
+   * @covers ::assertAllAssociativeArrays
+   */
+  public function testAssertAllAssociativeArrays() {
+    $this->assertTrue(Assertion::assertAllAssociativeArrays([]));
+    $this->assertTrue(Assertion::assertAllAssociativeArrays([[],[]]));
+    $this->assertFalse(Assertion::assertAllAssociativeArrays([[], 'foo']));
+  }
+
+  /**
+   * @covers ::assertStrictArray
+   */
+  public function testAssertStrictArray() {
+    $this->assertTrue(Assertion::assertStrictArray([]));
+    $this->assertTrue(Assertion::assertStrictArray(['bar','foo']));
+    $this->assertFalse(Assertion::assertStrictArray(['foo'=>'bar','bar'=>'foo']));
+  }
+
+  /**
+   * @covers ::assertAllStrictArrays
+   */
+  public function testAssertAllStrictArrays() {
+    $this->assertTrue(Assertion::assertAllStrictArrays([]));
+    $this->assertTrue(Assertion::assertAllStrictArrays([[],[]]));
+    $this->assertFalse(Assertion::assertAllStrictArrays([['foo'=>'bar','bar'=>'foo']]));
+  }
+
+  /**
+   * @covers ::assertAllHaveKey
+   */
+  public function testAssertAllHaveKey() {
+    $this->assertTrue(Assertion::assertAllHaveKey([]));
+    $this->assertTrue(Assertion::assertAllHaveKey([['foo'=>'bar','bar'=>'foo']]));
+    $this->assertTrue(Assertion::assertAllHaveKey([['foo'=>'bar','bar'=>'foo']], 'foo'));
+    $this->assertTrue(Assertion::assertAllHaveKey([['foo'=>'bar','bar'=>'foo']], 'bar', 'foo'));
+    $this->assertFalse(Assertion::assertAllHaveKey([['foo'=>'bar','bar'=>'foo']], 'bar', 'foo', 'moo'));
+  }
+
+  /**
+   * @covers ::assertAllIntegers
+   */
+  public function testAssertAllIntegers() {
+    $this->assertTrue(Assertion::assertAllIntegers([]));
+    $this->assertTrue(Assertion::assertAllIntegers([1,2,3]));
+    $this->assertFalse(Assertion::assertAllIntegers([1,2,3.14]));
+    $this->assertFalse(Assertion::assertAllIntegers([1,'2',3]));
+  }
+
+  /**
+   * @covers ::assertAllFloat
+   */
+  public function testAssertAllFloat() {
+    $this->assertTrue(Assertion::assertAllFloat([]));
+    $this->assertTrue(Assertion::assertAllFloat([1.0,2.1,3.14]));
+    $this->assertFalse(Assertion::assertAllFloat([1,2.1,3.14]));
+    $this->assertFalse(Assertion::assertAllFloat([1.0,'2',3]));
+    $this->assertFalse(Assertion::assertAllFloat(['Titanic']));
+  }
+
+  /**
+   * @covers ::assertAllCallable
+   */
+  public function testAllCallable() {
+    $this->assertTrue(Assertion::assertAllCallable([
+      'strchr',
+      [$this, 'callMe'],
+      [__CLASS__, 'callMeStatic'],
+      function() { return TRUE; }
+    ]));
+
+    $this->assertFalse(Assertion::assertAllCallable([
+      'strchr',
+      [$this, 'callMe'],
+      [__CLASS__, 'callMeStatic'],
+      function() { return TRUE; },
+      "I'm not callable"
+    ]));
+  }
+
+  /**
+   * @covers ::assertAllNotEmpty
+   */
+  public function testAllNotEmpty() {
+    $this->assertTrue(Assertion::assertAllNotEmpty([1,'two']));
+    $this->assertFalse(Assertion::assertAllNotEmpty(['']));
+  }
+
+  /**
+   * @covers ::assertAllNumeric
+   */
+  public function testAssertAllNumeric() {
+    $this->assertTrue(Assertion::assertAllNumeric([1,'2', 3.14]));
+    $this->assertFalse(Assertion::assertAllNumeric([1, 'two', 3.14]));
+  }
+
+  /**
+   * @covers ::assertAllMatch
+   */
+  public function testAssertAllMatch() {
+    $this->assertTrue(Assertion::assertAllMatch('f', ['fee', 'fi', 'fo']));
+    $this->assertTrue(Assertion::assertAllMatch('F', ['fee', 'fi', 'fo']));
+    $this->assertTrue(Assertion::assertAllMatch('f', ['fee', 'fi', 'fo'], TRUE));
+    $this->assertFalse(Assertion::assertAllMatch('F', ['fee', 'fi', 'fo'], TRUE));
+    $this->assertFalse(Assertion::assertAllMatch('e', ['fee', 'fi', 'fo']));
+    $this->assertFalse(Assertion::assertAllMatch('1', [12]));
+  }
+
+  /**
+   * @covers ::assertAllRegularExpressionMatch
+   */
+  public function testAssertAllRegularExpressionMatch() {
+    $this->assertTrue(Assertion::assertAllRegularExpressionMatch('/f/i', ['fee', 'fi', 'fo']));
+    $this->assertTrue(Assertion::assertAllRegularExpressionMatch('/F/i', ['fee', 'fi', 'fo']));
+    $this->assertTrue(Assertion::assertAllRegularExpressionMatch('/f/', ['fee', 'fi', 'fo']));
+    $this->assertFalse(Assertion::assertAllRegularExpressionMatch('/F/', ['fee', 'fi', 'fo']));
+    $this->assertFalse(Assertion::assertAllRegularExpressionMatch('/e/', ['fee', 'fi', 'fo']));
+    $this->assertFalse(Assertion::assertAllRegularExpressionMatch('/1/', [12]));
+  }
+
+  /**
+   * @covers ::assertAllObjects
+   */
+  public function testAssertAllObjects() {
+    $this->assertTrue(Assertion::assertAllObjects([new ArrayObject(), new ArrayObject()]));
+    $this->assertFalse(Assertion::assertAllObjects([new ArrayObject(), new ArrayObject(), 'foo']));
+    $this->assertTrue(Assertion::assertAllObjects([new ArrayObject(), new ArrayObject()], '\\Traversable'));
+    $this->assertFalse(Assertion::assertAllObjects([new ArrayObject(), new ArrayObject(), 'foo'], '\\Traversable'));
+    $this->assertFalse(Assertion::assertAllObjects([new ArrayObject(), new StringObject()], '\\Traversable'));
+    $this->assertTrue(Assertion::assertAllObjects([new ArrayObject(), new StringObject()], '\\Traversable', '\\Drupal\\Tests\\Component\\Assertion\\StringObject'));
+    $this->assertFalse(Assertion::assertAllObjects([new ArrayObject(), new StringObject(), new stdClass()], '\\ArrayObject', '\\Drupal\\Tests\\Component\\Assertion\\StringObject'));
+  }
+
+  /**
+   * Call me sometime.
+   *
+   * This method exists as part of the is_callable test.
+   */
+  public function callMe() {
+    return TRUE;
+  }
+
+  /**
+   * Call me static.
+   *
+   * Again, just a testing method.
+   */
+  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/core/tests/Drupal/Tests/Component/Assertion/AssertionTestTraitTest.php b/core/tests/Drupal/Tests/Component/Assertion/AssertionTestTraitTest.php
new file mode 100644
index 0000000..28b28e5
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Assertion/AssertionTestTraitTest.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\Tests\Component\AssertionTestTraitTest.
+ */
+
+namespace Drupal\Tests\Component\Assertion;
+
+use PHPUnit_Framework_TestCase;
+use Drupal\Component\Assertion\PHPUnitTestingTrait;
+
+/**
+ * Tests for the Assertion-aware traits in PHPUnit.
+ *
+ * @coversDefaultClass \Drupal\Component\Assertion\PHPUnitTestingTrait
+ *
+ * @group Assertion
+ */
+class AssertionTestTraitTest extends PHPUnit_Framework_TestCase {
+  use PHPUnitTestingTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    $this->startAssertionHandling();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function tearDown() {
+    $this->stopAssertionHandling();
+  }
+
+  /**
+   * Test the PHPUnit Assert() assist trait.
+   *
+   * This test is a bit unusual - it is testing a trait bound to itself instead
+   * of testing an outside object. This is done because the trait in question
+   * is designed to be bound to PHPUnit tests.
+   */
+  public function testBasics() {
+    // Normal assert().
+    assert('1 > 2');
+    $this->assertAssertionsRaised('1 > 2');
+
+    // Assert() called without a code string echoes an error message.
+    ob_start();
+    assert(1 > 2);
+    $output = ob_get_clean();
+    $this->assertEquals($output, $this->assertionsMustBeStrings);
+    $this->assertAssertionsRaised('');
+
+    // Assertion log should be empty after the above call.
+    $this->assertAssertionNotRaised();
+
+    // Test accumulation of assert() failures.
+    assert('1 > 2');
+    assert('4 < 2');
+    assert('false');
+
+    $this->assertAssertionsRaised('1 > 2', '4 < 2', 'false');
+  }
+
+  /**
+   * Tests if an exception is thrown when dieOnRaise is set.
+   *
+   * @expectedException \Drupal\Component\Assertion\AssertionException
+   */
+  public function testAssertionExceptionThrow() {
+    $this->dieOnRaise = TRUE;
+    assert('4 < 2');
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheTagsInvalidatorTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheTagsInvalidatorTest.php
index a2daba7..f60eb0f 100644
--- a/core/tests/Drupal/Tests/Core/Cache/CacheTagsInvalidatorTest.php
+++ b/core/tests/Drupal/Tests/Core/Cache/CacheTagsInvalidatorTest.php
@@ -19,17 +19,6 @@ class CacheTagsInvalidatorTest extends UnitTestCase {
 
   /**
    * @covers ::invalidateTags
-   *
-   * @expectedException \LogicException
-   * @expectedExceptionMessage Cache tags must be strings, array given.
-   */
-  public function testInvalidateTagsWithInvalidTags() {
-    $cache_tags_invalidator = new CacheTagsInvalidator();
-    $cache_tags_invalidator->invalidateTags(['node' => [2, 3, 5, 8, 13]]);
-  }
-
-  /**
-   * @covers ::invalidateTags
    * @covers ::addInvalidator
    */
   public function testInvalidateTags() {
diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheTest.php
index c2e61a1..2cdc030 100644
--- a/core/tests/Drupal/Tests/Core/Cache/CacheTest.php
+++ b/core/tests/Drupal/Tests/Core/Cache/CacheTest.php
@@ -18,48 +18,6 @@
 class CacheTest extends UnitTestCase {
 
   /**
-   * Provides a list of cache tags arrays.
-   *
-   * @return array
-   */
-  public function validateTagsProvider() {
-    return [
-      [[], FALSE],
-      [['foo'], FALSE],
-      [['foo', 'bar'], FALSE],
-      [['foo', 'bar', 'llama:2001988', 'baz', 'llama:14031991'], FALSE],
-      // Invalid.
-      [[FALSE], 'Cache tags must be strings, boolean given.'],
-      [[TRUE], 'Cache tags must be strings, boolean given.'],
-      [['foo', FALSE], 'Cache tags must be strings, boolean given.'],
-      [[NULL], 'Cache tags must be strings, NULL given.'],
-      [['foo', NULL], 'Cache tags must be strings, NULL given.'],
-      [[1337], 'Cache tags must be strings, integer given.'],
-      [['foo', 1337], 'Cache tags must be strings, integer given.'],
-      [[3.14], 'Cache tags must be strings, double given.'],
-      [['foo', 3.14], 'Cache tags must be strings, double given.'],
-      [[[]], 'Cache tags must be strings, array given.'],
-      [['foo', []], 'Cache tags must be strings, array given.'],
-      [['foo', ['bar']], 'Cache tags must be strings, array given.'],
-      [[new \stdClass()], 'Cache tags must be strings, object given.'],
-      [['foo', new \stdClass()], 'Cache tags must be strings, object given.'],
-    ];
-  }
-
-  /**
-   * @covers ::validateTags
-   *
-   * @dataProvider validateTagsProvider
-   */
-  public function testValidateTags(array $tags, $expected_exception_message) {
-    if ($expected_exception_message !== FALSE) {
-      $this->setExpectedException('LogicException', $expected_exception_message);
-    }
-    // If it doesn't throw an exception, validateTags() returns NULL.
-    $this->assertNull(Cache::validateTags($tags));
-  }
-
-  /**
    * Provides a list of pairs of cache tags arrays to be merged.
    *
    * @return array
diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheableMetadataTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheableMetadataTest.php
index f2dbd3e..e02613a 100644
--- a/core/tests/Drupal/Tests/Core/Cache/CacheableMetadataTest.php
+++ b/core/tests/Drupal/Tests/Core/Cache/CacheableMetadataTest.php
@@ -35,6 +35,7 @@ public function testMerge(CacheableMetadata $a, CacheableMetadata $b, CacheableM
     $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
       ->disableOriginalConstructor()
       ->getMock();
+    $cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
     $container = new ContainerBuilder();
     $container->set('cache_contexts_manager', $cache_contexts_manager);
     \Drupal::setContainer($container);
diff --git a/core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php b/core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php
index 52b6ef5..157007f 100644
--- a/core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php
+++ b/core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php
@@ -60,6 +60,7 @@ public function testMerge(BubbleableMetadata $a, CacheableMetadata $b, Bubbleabl
     $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
       ->disableOriginalConstructor()
       ->getMock();
+    $cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
     $container = new ContainerBuilder();
     $container->set('cache_contexts_manager', $cache_contexts_manager);
     $container->set('renderer', $renderer);
diff --git a/core/tests/Drupal/Tests/Core/Render/RendererTestBase.php b/core/tests/Drupal/Tests/Core/Render/RendererTestBase.php
index 7388c61..27d7187 100644
--- a/core/tests/Drupal/Tests/Core/Render/RendererTestBase.php
+++ b/core/tests/Drupal/Tests/Core/Render/RendererTestBase.php
@@ -104,6 +104,7 @@ protected function setUp() {
     $this->cacheContextsManager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
       ->disableOriginalConstructor()
       ->getMock();
+    $this->cacheContextsManager->method('assertValidTokens')->willReturn(TRUE);
     $this->cacheContextsManager->expects($this->any())
       ->method('convertTokensToKeys')
       ->willReturnCallback(function($context_tokens) {
diff --git a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php
index 57edd51..839b0e1 100644
--- a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php
+++ b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php
@@ -62,6 +62,7 @@ protected function setUp() {
     $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
       ->disableOriginalConstructor()
       ->getMock();
+    $cache_contexts_manager->method('assertValidTokens')->willReturn(TRUE);
     $container = new ContainerBuilder();
     $container->set('cache_contexts_manager', $cache_contexts_manager);
     \Drupal::setContainer($container);
diff --git a/sites/example.settings.local.php b/sites/example.settings.local.php
index 56fed6f..98fe3f2 100644
--- a/sites/example.settings.local.php
+++ b/sites/example.settings.local.php
@@ -12,6 +12,20 @@
  */
 
 /**
+ * Assertions
+ *
+ * Drupal uses assert statements to perform validations that are only
+ * necessary during module and theme development, and that slow the system
+ * down. By default the statements are turned off in the .htaccess file.
+ * Here we turn them back on which should be sufficient for most projects,
+ * but assert statements located before the DrupalKernel parses this file
+ * will not be ran unless you modify the .htaccess file. We also set the
+ * system to halt on assert fail, just in case.
+ */
+assert_options(ASSERT_ACTIVE, 1);
+assert_options(ASSERT_BAIL, 1);
+
+/**
  * Enable local development services.
  */
 $settings['container_yamls'][] = DRUPAL_ROOT . '/sites/development.services.yml';
