diff --git a/readme.md b/readme.md index cd22c155f9..e540fce64c 100644 --- a/readme.md +++ b/readme.md @@ -519,6 +519,9 @@ echo $faker->name; // 'Jess Mraz I'; > // good > $faker->realText($faker->numberBetween(10,20)); > ``` +> +> **Tip**: When the faker object is destroyed, the seed is restored to generate unpredictable values (default behavior for mt_rand that is used internally). But you can't guess when the php garbage collector is going to collect the faker object. It can occur during a values generation sequence from another instance of faker (like in a test suite). In this case it will break your predictable values suite. To prevent this kind of problem, when you've finished to generate values, you should use `restoreSeed` on your faker instance to control the seed restore instant. +> diff --git a/src/Faker/Generator.php b/src/Faker/Generator.php index 7c757c3790..ecc6c26811 100644 --- a/src/Faker/Generator.php +++ b/src/Faker/Generator.php @@ -199,6 +199,7 @@ class Generator { protected $providers = array(); protected $formatters = array(); + protected $seedRestored = false; public function addProvider($provider) { @@ -223,6 +224,16 @@ public function seed($seed = null) } } + public function restoreSeed() + { + if ($this->seedRestored) { + return; + } + + $this->seed(); + $this->seedRestored = true; + } + public function format($formatter, $arguments = array()) { return call_user_func_array($this->getFormatter($formatter), $arguments); @@ -287,6 +298,6 @@ public function __call($method, $attributes) public function __destruct() { - $this->seed(); + $this->restoreSeed(); } } diff --git a/test/Faker/GeneratorTest.php b/test/Faker/GeneratorTest.php index 706b0a8ff0..5a2bb6e0ca 100644 --- a/test/Faker/GeneratorTest.php +++ b/test/Faker/GeneratorTest.php @@ -124,6 +124,32 @@ public function testSeed() $generator->seed('10'); $this->assertTrue(true, 'seeding with a non int value doesn\'t throw an exception'); } + + public function testRestoreSeedPreventSeedBreak() + { + $generator1 = new Generator; + $generator1->seed(0); + + $generated1 = array(); + for ($i=0; $i<5; $i++) { + $generated1[] = mt_rand(1, 10); + } + $generator1->restoreSeed(); + $this->assertEquals(array(5, 6, 8, 2, 7), $generated1); + + $generator2 = new Generator; + $generator2->seed(0); + + $generated2 = array(); + for ($i=0; $i<5; $i++) { + if ($i == 2) { + $generator1->__destruct(); + } + $generated2[] = mt_rand(1, 10); + } + $generator2->restoreSeed(); + $this->assertEquals(array(5, 6, 8, 2, 7), $generated2); + } } final class FooProvider