summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2013-09-04 12:09:19 +0100
committerNathaniel Catchpole2013-09-04 12:09:19 +0100
commit970fdb9e479f15291a9b54ea429c68e1b621607a (patch)
tree67e1a64d3332ba80b7fe4d561140fd1511c731a2
parent42ca6403e07b8a91c8c24d1d16f645cf683ac9ae (diff)
Issue #2032453 by alexpott, tsphethean: Fixed WebTestBase::randomString returning a string containing a $ followed by a number causes assertLink() to fail it's xpath match.8.0-alpha3
-rw-r--r--core/lib/Drupal/Component/Utility/Random.php37
-rw-r--r--core/modules/simpletest/lib/Drupal/simpletest/TestBase.php57
-rw-r--r--core/modules/simpletest/tests/Drupal/simpletest/Tests/TestBaseTest.php71
-rw-r--r--core/tests/Drupal/Tests/Component/Utility/RandomTest.php69
-rw-r--r--core/tests/Drupal/Tests/UnitTestCase.php25
5 files changed, 232 insertions, 27 deletions
diff --git a/core/lib/Drupal/Component/Utility/Random.php b/core/lib/Drupal/Component/Utility/Random.php
index df989c0..2712fba 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,20 @@ 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 generated string is not
+ // unique or if $validator is a callable that 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 +71,20 @@ class Random {
$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 +110,7 @@ class Random {
*
* @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 +124,10 @@ class Random {
$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 +143,11 @@ class Random {
* 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 91925e1..c0a9102 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -181,6 +181,13 @@ abstract class TestBase {
protected $configImporter;
/**
+ * The random generator.
+ *
+ * @var \Drupal\Component\Utility\Random
+ */
+ protected $randomGenerator;
+
+ /**
* Constructor for Test.
*
* @param $test_id
@@ -1194,7 +1201,38 @@ abstract class TestBase {
* @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::string()
+ *
+ * @param string $string
+ * The random string to validate.
+ *
+ * @return bool
+ * TRUE if the random string is valid, FALSE if not.
+ */
+ public function randomStringValidate($string) {
+ // Consecutive spaces causes issues for
+ // Drupal\simpletest\WebTestBase::assertLink().
+ if (preg_match('/\s{2,}/', $string)) {
+ return FALSE;
+ }
+
+ // Starting with a space means that length might not be what is expected.
+ if (preg_match('/^\s/', $string)) {
+ return FALSE;
+ }
+
+ // Ending with a space means that length might not be what is expected.
+ if (preg_match('/\s$/', $string)) {
+ return FALSE;
+ }
+
+ return TRUE;
}
/**
@@ -1212,7 +1250,7 @@ abstract class TestBase {
* @see \Drupal\Component\Utility\Random::name()
*/
public function randomName($length = 8) {
- return Random::name($length, TRUE);
+ return $this->getRandomGenerator()->name($length, TRUE);
}
/**
@@ -1228,7 +1266,20 @@ abstract class TestBase {
* @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/tests/Drupal/simpletest/Tests/TestBaseTest.php b/core/modules/simpletest/tests/Drupal/simpletest/Tests/TestBaseTest.php
new file mode 100644
index 0000000..d645149
--- /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 \PHPUnit_Framework_MockObject_MockObject
+ */
+ 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 $string
+ * The string to validate.
+ * @param bool $expected
+ * The expected result of the validation.
+ *
+ * @see \Drupal\simpletest\TestBase::randomStringValidate().
+ *
+ * @dataProvider randomStringValidateProvider
+ */
+ public function testRandomStringValidate($string, $expected) {
+ $actual = $this->stub->randomStringValidate($string);
+ $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..b9c7a4e 100644
--- a/core/tests/Drupal/Tests/Component/Utility/RandomTest.php
+++ b/core/tests/Drupal/Tests/Component/Utility/RandomTest.php
@@ -18,6 +18,15 @@ use Drupal\Tests\UnitTestCase;
*/
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 @@ class RandomTest extends UnitTestCase {
}
/**
- * 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 @@ class RandomTest extends UnitTestCase {
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 @@ class RandomTest extends UnitTestCase {
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 @@ class RandomTest extends UnitTestCase {
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 @@ class RandomTest extends UnitTestCase {
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 @@ class RandomTest extends UnitTestCase {
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 $string
+ * The random string to validate.
+ *
+ * @return bool
+ * TRUE if the random string is valid, FALSE if not.
+ */
+ public function _RandomStringValidate($string) {
+ if (empty($this->firstStringGenerated)) {
+ $this->firstStringGenerated = $string;
+ return FALSE;
+ }
+ return TRUE;
+ }
}
diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php
index 576c015..9c36603 100644
--- a/core/tests/Drupal/Tests/UnitTestCase.php
+++ b/core/tests/Drupal/Tests/UnitTestCase.php
@@ -15,6 +15,13 @@ use Drupal\Component\Utility\Random;
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 @@ abstract class UnitTestCase extends \PHPUnit_Framework_TestCase {
* @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->getRandomGenerator()->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