diff --git a/src/Generator.php b/src/Generator.php index ee01a41e94..b55b077388 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -560,6 +560,13 @@ class Generator private $container; + /** + * In order to prevent resetting the seed while another Generator instance is still alive, we keep track of the + * total, global number of Generators being "active". Incremented in __construct, decremented in __destruct. + * This is necessary, because __destruct modifies global state (`mt_srand`). + */ + private static int $generatorsAlive = 0; + /** * @var UniqueGenerator */ @@ -568,6 +575,7 @@ class Generator public function __construct(ContainerInterface $container = null) { $this->container = $container ?: Container\ContainerBuilder::withDefaultExtensions()->build(); + ++self::$generatorsAlive; } /** @@ -963,7 +971,9 @@ public function __call($method, $attributes) public function __destruct() { - $this->seed(); + if ((--self::$generatorsAlive) <= 0) { + $this->seed(); + } } public function __wakeup() diff --git a/test/GeneratorTest.php b/test/GeneratorTest.php index 0a256e94df..0f4493c319 100644 --- a/test/GeneratorTest.php +++ b/test/GeneratorTest.php @@ -11,6 +11,7 @@ use Faker\Extension\BloodExtension; use Faker\Extension\ExtensionNotFound; use Faker\Extension\FileExtension; +use Faker\Factory; use Faker\Generator; use Faker\Provider; use Faker\UniqueGenerator; @@ -327,4 +328,24 @@ public function word(): string $uniqueGenerator->word(); } + + public function testDestructingOldGeneratorDoesNotResetTheSeed(): void + { + $faker = Factory::create('en_US'); + $faker->seed(1); + + $expected1 = $faker->numberBetween(1000, 10000); + $expected2 = $faker->numberBetween(1000, 10000); + $faker = null; + + for ($i = 0; $i < 3; ++$i) { + $faker = Factory::create('en_US'); + $faker->seed(1); + self::assertSame($expected1, $faker->numberBetween(1000, 10000)); + + gc_collect_cycles(); + + self::assertSame($expected2, $faker->numberBetween(1000, 10000)); + } + } }