diff --git a/core/lib/Drupal/Component/Utility/Random.php b/core/lib/Drupal/Component/Utility/Random.php new file mode 100644 index 0000000..b39899f --- /dev/null +++ b/core/lib/Drupal/Component/Utility/Random.php @@ -0,0 +1,139 @@ +{$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 1b746e6..28a7bd6 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -7,6 +7,7 @@ namespace Drupal\simpletest; +use Drupal\Component\Utility\Random; use Drupal\Core\Database\Database; use Drupal\Component\Utility\Settings; use Drupal\Core\Config\ConfigImporter; @@ -179,20 +180,6 @@ protected $configImporter; /** - * A list of unique strings generated by randomString(). - * - * @var array - */ - protected $randomStrings = array(); - - /** - * A list of unique names generated by randomName(). - * - * @var array - */ - protected $randomNames = array(); - - /** * Constructor for Test. * * @param $test_id @@ -1168,62 +1155,38 @@ protected function settingsSet($name, $value) { /** * Generates a unique random string of ASCII characters of codes 32 to 126. * - * The generated string includes alpha-numeric characters and common - * miscellaneous characters. Use this method when testing general input - * where the content is not restricted. - * * Do not use this method when special characters are not possible (e.g., in * machine or file names that have already been validated); instead, use - * Drupal\simpletest\TestBase::randomName(). + * \Drupal\simpletest\TestBase::randomName(). * - * @param $length + * @param int $length * Length of random string to generate. * - * @return - * Randomly generated string. + * @return string + * Randomly generated unique string. * - * @see Drupal\simpletest\TestBase::randomName() + * @see \Drupal\Component\Utility\Random::string() */ public function randomString($length = 8) { - do { - $str = ''; - for ($i = 0; $i < $length; $i++) { - $str .= chr(mt_rand(32, 126)); - } - } while (isset($this->randomStrings[$str])); - return $str; + return Random::string($length, TRUE); } /** * Generates a unique random string containing letters and numbers. * - * The string will always start with a letter. The letters may be upper or - * lower case. This method is better for restricted inputs that do not - * accept certain characters. For example, when testing input fields that - * require machine readable values (i.e. without spaces and non-standard - * characters) this method is best. - * * Do not use this method when testing unvalidated user input. Instead, use - * Drupal\simpletest\TestBase::randomString(). + * \Drupal\simpletest\TestBase::randomString(). * - * @param $length + * @param int $length * Length of random string to generate. * - * @return - * Randomly generated string. + * @return string + * Randomly generated unique string. * - * @see Drupal\simpletest\TestBase::randomString() + * @see \Drupal\Component\Utility\Random::name() */ public function randomName($length = 8) { - do { - $values = array_merge(range(65, 90), range(97, 122), range(48, 57)); - $max = count($values) - 1; - $str = chr(mt_rand(97, 122)); - for ($i = 1; $i < $length; $i++) { - $str .= chr($values[mt_rand(0, $max)]); - } - } while (isset($this->randomNames[$str])); - return $str; + return Random::name($length, TRUE); } /** @@ -1235,15 +1198,11 @@ public function randomName($length = 8) { * @return \stdClass * The generated object, with the specified number of random keys. Each key * has a random string value. + * + * @see \Drupal\Component\Utility\Random::object() */ public function randomObject($size = 4) { - $object = new \stdClass(); - for ($i = 0; $i < $size; $i++) { - $random_key = $this->randomName(); - $random_value = $this->randomString(); - $object->{$random_key} = $random_value; - } - return $object; + return Random::object($size); } /** diff --git a/core/tests/Drupal/Tests/Component/Utility/RandomTest.php b/core/tests/Drupal/Tests/Component/Utility/RandomTest.php new file mode 100644 index 0000000..53df468 --- /dev/null +++ b/core/tests/Drupal/Tests/Component/Utility/RandomTest.php @@ -0,0 +1,116 @@ + 'Random data generation tests', + 'description' => 'Confirm that Random::name() and Random::string() work correctly.', + 'group' => 'Common', + ); + } + + /** + * Tests Random::string(). + */ + function testRandomStringUniqueness() { + $strings = array(); + for ($i = 0; $i <= 50; $i++) { + $str = Random::string(1, TRUE); + $this->assertFalse(isset($strings[$str]), String::format('Generated duplicate random string !string', array('!string' => $str))); + $strings[$str] = TRUE; + } + } + + /** + * Tests Random::string(). + */ + function testRandomNamesUniqueness() { + $names = array(); + for ($i = 0; $i <= 10; $i++) { + $str = Random::name(1, TRUE); + $this->assertFalse(isset($names[$str]), String::format('Generated duplicate random name !name', array('!name' => $str))); + $names[$str] = TRUE; + } + } + + /** + * Tests infinite loop prevention in Random::name(). + * + * @expectedException RuntimeException + */ + public function testRandomNameException() { + // There are fewer than 100 possibilities so an exception should occur to + // prevent infinite loops. + for ($i = 0; $i <= 100; $i++) { + $str = Random::name(1, TRUE); + $names[$str] = TRUE; + } + } + + /** + * Tests infinite loop prevention in Random::string(). + * + * @expectedException RuntimeException + */ + public function testRandomStringException() { + // There are fewer than 100 possibilities so an exception should occur to + // prevent infinite loops. + for ($i = 0; $i <= 100; $i++) { + $str = Random::string(1, TRUE); + $names[$str] = TRUE; + } + } + + /** + * Tests Random::name() if uniqueness is not enforced. + */ + public function testRandomNameNonUnique() { + // There are fewer than 100 possibilities if we were forcing uniqueness so + // exception would occur. + for ($i = 0; $i <= 100; $i++) { + Random::name(1); + } + $this->assertTrue(TRUE, 'No exception thrown when uniqueness is not enforced.'); + } + + /** + * Tests Random::string() if uniqueness is not enforced. + */ + public function testRandomStringNonUnique() { + // There are fewer than 100 possibilities if we were forcing uniqueness so + // exception would occur. + for ($i = 0; $i <= 100; $i++) { + Random::string(1); + } + $this->assertTrue(TRUE, 'No exception thrown when uniqueness is not enforced.'); + } + + /** + * Tests Random::object() to ensure it has the expected number of properties. + */ + public function testRandomObject() { + // For values of 0 and 1 random object will have a different execution path. + for ($i = 0; $i <= 1; $i++) { + $obj = Random::object($i); + $this->assertEquals($i, count(get_object_vars($obj)), 'Generated random object has expected number of properties'); + } + } + +} diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php index 1856011..727976f 100644 --- a/core/tests/Drupal/Tests/UnitTestCase.php +++ b/core/tests/Drupal/Tests/UnitTestCase.php @@ -7,6 +7,8 @@ namespace Drupal\Tests; +use Drupal\Component\Utility\Random; + /** * Provides a base class and helpers for Drupal unit tests. */ @@ -33,33 +35,18 @@ public static function getInfo() { } /** - * Generates a random string containing letters and numbers. - * - * The string will always start with a letter. The letters may be upper or - * lower case. This method is better for restricted inputs that do not accept - * certain characters. For example, when testing input fields that require - * machine readable values (i.e. without spaces and non-standard characters) - * this method is best. - * - * Do not use this method when testing unvalidated user input. Instead, use - * Drupal\simpletest\TestBase::randomString(). + * Generates a unique random string containing letters and numbers. * * @param int $length * Length of random string to generate. * * @return string - * Randomly generated string. + * Randomly generated unique string. * - * @see Drupal\simpletest\TestBase::randomString() + * @see \Drupal\Component\Utility::string() */ - public static function randomName($length = 8) { - $values = array_merge(range(65, 90), range(97, 122), range(48, 57)); - $max = count($values) - 1; - $str = chr(mt_rand(97, 122)); - for ($i = 1; $i < $length; $i++) { - $str .= chr($values[mt_rand(0, $max)]); - } - return $str; + public function randomName($length = 8) { + return Random::name($length, TRUE); } /**