diff --git a/core/lib/Drupal/Component/Utility/Random.php b/core/lib/Drupal/Component/Utility/Random.php
index df989c0..1533e65 100644
--- a/core/lib/Drupal/Component/Utility/Random.php
+++ b/core/lib/Drupal/Component/Utility/Random.php
@@ -27,14 +27,14 @@ class Random {
    *
    * @var array
    */
-  static protected $strings = array();
+  protected $strings = array();
 
   /**
    * A list of unique names generated by name().
    *
    * @var array
    */
-  static protected $names = array();
+  protected $names = array();
 
   /**
    * Generates a random string of ASCII characters of codes 32 to 126.
@@ -48,15 +48,21 @@ class Random {
    * @param bool $unique
    *   (optional) If TRUE ensures that the random string returned is unique.
    *   Defaults to FALSE.
+   * @param callable $validator
+   *   (optional) A callable to validate the the string. Defaults to NULL.
    *
    * @return string
    *   Randomly generated string.
    *
    * @see \Drupal\Component\Utility\Random::name()
    */
-  public static function string($length = 8, $unique = FALSE) {
+  public function string($length = 8, $unique = FALSE, $validator = NULL) {
     $counter = 0;
 
+    // Continue to loop if $unique is TRUE and the string has been generated
+    // already or if $callable is not null and the validate method returns
+    // FALSE. To generate a random string this loop must be carried out at least
+    // once.
     do {
       if ($counter == static::MAXIMUM_TRIES) {
         throw new \RuntimeException('Unable to generate a unique random name');
@@ -66,10 +72,20 @@ public static function string($length = 8, $unique = FALSE) {
         $str .= chr(mt_rand(32, 126));
       }
       $counter++;
-    } while ($unique && isset(static::$strings[$str]));
+
+      $continue = FALSE;
+      if ($unique) {
+        $continue = isset($this->strings[$str]);
+      }
+      if (!$continue && is_callable($validator)) {
+        // If the validator callback returns FALSE generate another random
+        // string.
+        $continue = !call_user_func($validator, $str);
+      }
+    } while ($continue);
 
     if ($unique) {
-      static::$strings[$str] = TRUE;
+      $this->strings[$str] = TRUE;
     }
 
     return $str;
@@ -95,7 +111,7 @@ public static function string($length = 8, $unique = FALSE) {
    *
    * @see \Drupal\Component\Utility\Random::string()
    */
-  public static function name($length = 8, $unique = FALSE) {
+  public function name($length = 8, $unique = FALSE) {
     $values = array_merge(range(65, 90), range(97, 122), range(48, 57));
     $max = count($values) - 1;
     $counter = 0;
@@ -109,10 +125,10 @@ public static function name($length = 8, $unique = FALSE) {
         $str .= chr($values[mt_rand(0, $max)]);
       }
       $counter++;
-    } while ($unique && isset(static::$names[$str]));
+    } while ($unique && isset($this->names[$str]));
 
     if ($unique) {
-      static::$names[$str] = TRUE;
+      $this->names[$str] = TRUE;
     }
 
     return $str;
@@ -128,11 +144,11 @@ public static function name($length = 8, $unique = FALSE) {
    *   The generated object, with the specified number of random keys. Each key
    *   has a random string value.
    */
-  public static function object($size = 4) {
+  public function object($size = 4) {
     $object = new \stdClass();
     for ($i = 0; $i < $size; $i++) {
-      $random_key = static::name();
-      $random_value = static::string();
+      $random_key = $this->name();
+      $random_value = $this->string();
       $object->{$random_key} = $random_value;
     }
     return $object;
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 3eb5c84..4baa3fe 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -180,6 +180,13 @@
   protected $configImporter;
 
   /**
+   * The random generator.
+   *
+   * @var \Drupal\Component\Utility\Random
+   */
+  protected $randomGenerator;
+
+  /**
    * Constructor for Test.
    *
    * @param $test_id
@@ -1169,7 +1176,38 @@ protected function settingsSet($name, $value) {
    * @see \Drupal\Component\Utility\Random::string()
    */
   public function randomString($length = 8) {
-    return Random::string($length, TRUE);
+    return $this->getRandomGenerator()->string($length, TRUE, array($this, 'randomStringValidate'));
+  }
+
+  /**
+   * Callback for random string validation.
+   *
+   * @see \Drupal\Component\Utility\Random::name()
+   *
+   * @param string $str
+   *   The random string to validate.
+   *
+   * @return bool
+   *   TRUE if the random string is valid, FALSE if not.
+   */
+  public function randomStringValidate($str) {
+    // Consecutive spaces causes issues for
+    // Drupal\simpletest\WebTestBase::assertLink().
+    if (preg_match('/\s{2,}/', $str)) {
+      return FALSE;
+    }
+
+    // Starting with a space means that length might not be what is expected.
+    if (preg_match('/^\s/', $str)) {
+      return FALSE;
+    }
+
+    // Ending with a space means that length might not be what is expected.
+    if (preg_match('/\s$/', $str)) {
+      return FALSE;
+    }
+
+    return TRUE;
   }
 
   /**
@@ -1187,7 +1225,7 @@ public function randomString($length = 8) {
    * @see \Drupal\Component\Utility\Random::name()
    */
   public function randomName($length = 8) {
-    return Random::name($length, TRUE);
+    return $this->getRandomGenerator()->name($length, TRUE);
   }
 
   /**
@@ -1203,7 +1241,20 @@ public function randomName($length = 8) {
    * @see \Drupal\Component\Utility\Random::object()
    */
   public function randomObject($size = 4) {
-    return Random::object($size);
+    return $this->getRandomGenerator()->object($size);
+  }
+
+  /**
+   * Gets the random generator for the utility methods.
+   *
+   * @return \Drupal\Component\Utility\Random
+   *   The random generator
+   */
+  protected function getRandomGenerator() {
+    if (!is_object($this->randomGenerator)) {
+      $this->randomGenerator = new Random();
+    }
+    return $this->randomGenerator;
   }
 
   /**
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/WebTestBaseTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/WebTestBaseTest.php
new file mode 100644
index 0000000..2bed56a
--- /dev/null
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/WebTestBaseTest.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\simpletest\Tests\WebTestBaseTest.
+ */
+
+namespace Drupal\simpletest\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests helper methods provided by the WebTestBase class.
+ */
+class WebTestBaseTest extends WebTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'WebTestBase helper functions test',
+      'description' => 'Test helper functions provided by the WebTestBase class.',
+      'group' => 'Simpletest',
+    );
+  }
+
+  /**
+   * Tests the behaviour of Drupal\simpletest\WebTestBase::assertLink().
+   */
+  public function testAsertLink() {
+    $link_texts = array(
+      'curry paste',
+      'thai green curry paste',
+      'Number\\9',
+      'Number\9',
+      'Number9',
+      'Number9\\',
+      '$7@|{v$S',
+    );
+
+    // Set up some links to test.
+    $this->content = '';
+    foreach ($link_texts as $link) {
+      $this->content .= '<a href="">' . $link .'</a>';
+    }
+
+    foreach ($link_texts as $link) {
+      $result = $this->assertLink($link);
+      $this->assertTrue($result, 'The assertLink method found link.');
+    }
+  }
+
+}
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 8e295b3..07b8622 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -1877,7 +1877,7 @@ protected function buildXPathQuery($xpath, array $args = array()) {
         // Return the string.
         $value = count($parts) > 1 ? 'concat(' . implode(', \'"\', ', $parts) . ')' : $parts[0];
       }
-      $xpath = preg_replace('/' . preg_quote($placeholder) . '\b/', $value, $xpath);
+      $xpath = str_replace($placeholder, $value, $xpath);
     }
     return $xpath;
   }
diff --git a/core/modules/simpletest/tests/Drupal/simpletest/Tests/TestBaseTest.php b/core/modules/simpletest/tests/Drupal/simpletest/Tests/TestBaseTest.php
new file mode 100644
index 0000000..27e3e7b
--- /dev/null
+++ b/core/modules/simpletest/tests/Drupal/simpletest/Tests/TestBaseTest.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\simpletest\TestBaseTest.
+ */
+
+namespace Drupal\simpletest\Tests;
+
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests helper methods provided by the abstract TestBase class.
+ */
+class TestBaseTest extends UnitTestCase {
+
+  /**
+   * A stub built using the TestBase class.
+   *
+   * @var object
+   */
+  protected $stub;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'TestBase helper functions test',
+      'description' => 'Test helper functions provided by the TestBase abstract class.',
+      'group' => 'Simpletest',
+
+    );
+  }
+
+  protected function setUp() {
+    $this->stub = $this->getMockForAbstractClass('Drupal\simpletest\TestBase');
+  }
+
+  /**
+   * Provides data for the random string validation test.
+   *
+   * @return array
+   *   An array of values passed to the test method.
+   */
+  public function randomStringValidateProvider () {
+    return array(
+      array(' curry paste', FALSE),
+      array('curry paste ', FALSE),
+      array('curry  paste', FALSE),
+      array('curry   paste', FALSE),
+      array('curry paste', TRUE),
+      array('thai green curry paste', TRUE),
+    );
+  }
+
+  /**
+   * Tests the random strings validation rules.
+   *
+   * @param string $str
+   *   The string to validate.
+   * @param bool $expected
+   *   The expected result of the validation.
+   *
+   * @see \Drupal\simpletest\TestBase::randomStringValidate().
+   *
+   * @dataProvider randomStringValidateProvider
+   */
+  public function testRandomStringValidate($str, $expected) {
+    $actual = $this->stub->randomStringValidate($str);
+    $this->assertEquals($expected, $actual);
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Component/Utility/RandomTest.php b/core/tests/Drupal/Tests/Component/Utility/RandomTest.php
index 894ecc2..dfff5bc 100644
--- a/core/tests/Drupal/Tests/Component/Utility/RandomTest.php
+++ b/core/tests/Drupal/Tests/Component/Utility/RandomTest.php
@@ -18,6 +18,15 @@
  */
 class RandomTest extends UnitTestCase {
 
+  /**
+   * The first random string passed to the test callback.
+   *
+   * @see \Drupal\Tests\Component\Utility\RandomTest::_RandomStringValidate
+   *
+   * @var string
+   */
+  protected $firstStringGenerated = '';
+
   public static function getInfo() {
     return array(
       'name' => 'Random data generation tests',
@@ -27,28 +36,30 @@ public static function getInfo() {
   }
 
   /**
-   * Tests unique random name generation.
+   * Tests unique random string generation.
    *
-   * @see \Drupal\Component\Utility\Random::name()
+   * @see \Drupal\Component\Utility\Random::string()
    */
   public function testRandomStringUniqueness() {
     $strings = array();
+    $random = new Random();
     for ($i = 0; $i <= 50; $i++) {
-      $str = Random::string(1, TRUE);
+      $str = $random->string(1, TRUE);
       $this->assertFalse(isset($strings[$str]), String::format('Generated duplicate random string !string', array('!string' => $str)));
       $strings[$str] = TRUE;
     }
   }
 
   /**
-   * Tests unique random string generation.
+   * Tests unique random name generation.
    *
-   * @see \Drupal\Component\Utility\Random::string()
+   * @see \Drupal\Component\Utility\Random::name()
    */
   public function testRandomNamesUniqueness() {
     $names = array();
+    $random = new Random();
     for ($i = 0; $i <= 10; $i++) {
-      $str = Random::name(1, TRUE);
+      $str = $random->name(1, TRUE);
       $this->assertFalse(isset($names[$str]), String::format('Generated duplicate random name !name', array('!name' => $str)));
       $names[$str] = TRUE;
     }
@@ -64,8 +75,9 @@ public function testRandomNamesUniqueness() {
   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);
+      $str = $random->name(1, TRUE);
       $names[$str] = TRUE;
     }
   }
@@ -80,8 +92,9 @@ public function testRandomNameException() {
   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);
+      $str = $random->string(1, TRUE);
       $names[$str] = TRUE;
     }
   }
@@ -94,8 +107,9 @@ public function testRandomStringException() {
   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);
+      $random->name(1);
     }
     $this->assertTrue(TRUE, 'No exception thrown when uniqueness is not enforced.');
   }
@@ -108,8 +122,9 @@ public function testRandomNameNonUnique() {
   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);
+      $random->string(1);
     }
     $this->assertTrue(TRUE, 'No exception thrown when uniqueness is not enforced.');
   }
@@ -122,10 +137,42 @@ public function testRandomStringNonUnique() {
   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);
+      $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.
+   *
+   * @see \Drupal\Component\Utility\Random::name()
+   */
+  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 $str
+   *   The random string to validate.
+   *
+   * @return bool
+   *   TRUE if the random string is valid, FALSE if not.
+   */
+  public function _RandomStringValidate($str) {
+    if (empty($this->firstStringGenerated)) {
+      $this->firstStringGenerated = $str;
+      return FALSE;
+    }
+    return TRUE;
+  }
 }
diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php
index 727976f..907df01 100644
--- a/core/tests/Drupal/Tests/UnitTestCase.php
+++ b/core/tests/Drupal/Tests/UnitTestCase.php
@@ -15,6 +15,13 @@
 abstract class UnitTestCase extends \PHPUnit_Framework_TestCase {
 
   /**
+   * The random generator.
+   *
+   * @var \Drupal\Component\Utility\Random
+   */
+  protected $randomGenerator;
+
+  /**
    * This method exists to support the simpletest UI runner.
    *
    * It should eventually be replaced with something native to phpunit.
@@ -43,13 +50,27 @@ public static function getInfo() {
    * @return string
    *   Randomly generated unique string.
    *
-   * @see \Drupal\Component\Utility::string()
+   * @see \Drupal\Component\Utility\Random::name()
    */
   public function randomName($length = 8) {
-    return Random::name($length, TRUE);
+    return $this->randomGenerator()->name($length, TRUE);
   }
 
   /**
+   * Gets the random generator for the utility methods.
+   *
+   * @return \Drupal\Component\Utility\Random
+   *   The random generator
+   */
+  protected function getRandomGenerator() {
+    if (!is_object($this->randomGenerator)) {
+      $this->randomGenerator = new Random();
+    }
+    return $this->randomGenerator;
+  }
+
+
+  /**
    * Returns a stub config factory that behaves according to the passed in array.
    *
    * Use this to generate a config factory that will return the desired values
