summaryrefslogtreecommitdiff
path: root/t/run
diff options
context:
space:
mode:
authorYves Orton <demerphq@gmail.com>2022-08-05 13:18:02 +0200
committerYves Orton <demerphq@gmail.com>2022-08-12 22:29:05 +0200
commitbf2a3dae9f4f828fd1f2f8aaf4769f96520c9552 (patch)
treeb58ad50f0d8d828bb5a890686e0ce7e82ae529ae /t/run
parent08da5deb5d0c842dab3fe5f4f5a450972a0eb67c (diff)
downloadperl-bf2a3dae9f4f828fd1f2f8aaf4769f96520c9552.tar.gz
Add a new env var PERL_RAND_SEED
This env var can be used to trigger a repeatable run of a script which calls C<srand()> with no arguments, either explicitly or implicitly via use of C<rand()> prior to calling srand(). This is implemented in such a way that calling C<srand()> with no arguments in forks or subthreads (again explicitly or implicitly) will receive their own seed but the seeds they receive will be repeatable. This is intended for debugging and perl development performance testing, and for running the test suite consistently. It is documented that the exact seeds used to initialize the random state are unspecified, and that they may change between releases or even builds. The only guarantee provided is that the same perl executable will produce the same results twice all other things being equal. In practice and in core testing we do expect consistency, but adding the tightest set of restrictions on our commitments seemed sensible. The env var is ignored when perl is run setuid or setgid similarly to the C<PERL_INTERNAL_RAND_SEED> env var.
Diffstat (limited to 't/run')
-rw-r--r--t/run/runenv_randseed.t68
1 files changed, 68 insertions, 0 deletions
diff --git a/t/run/runenv_randseed.t b/t/run/runenv_randseed.t
new file mode 100644
index 0000000000..b0ec6072b8
--- /dev/null
+++ b/t/run/runenv_randseed.t
@@ -0,0 +1,68 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ @INC = '../lib';
+ require './test.pl';
+ require Config;
+ Config->import;
+}
+
+skip_all_without_config('d_fork');
+skip_all("This perl is built with NO_PERL_RAND_SEED")
+ if $Config{ccflags} =~ /-DNO_PERL_RAND_SEED\b/;
+use strict;
+use warnings;
+
+for (1..2) {
+ local $ENV{PERL_RAND_SEED} = 1;
+ fresh_perl_is("print map { chr(rand(26)+65) } 1..10",
+ "BLVIOAEZTJ", undef, "Test randomness with PERL_RAND_SEED=1");
+}
+
+for (1..2) {
+ local $ENV{PERL_RAND_SEED} = 2;
+ fresh_perl_is("print map { chr(rand(26)+65) } 1..10",
+ "XEOUOFRPQZ", undef, "Test randomness with PERL_RAND_SEED=2");
+}
+
+my %got;
+for my $try (1..10) {
+ local $ENV{PERL_RAND_SEED};
+ my ($out,$err)= runperl_and_capture({}, ['-e',"print map { chr(rand(26)+65) } 1..10;"]);
+ if ($err) { diag $err }
+ $got{$out}++;
+}
+ok(8 <= keys %got, "Got at least 8 different strings");
+for (1..2) {
+ local $ENV{PERL_RAND_SEED} = 1;
+ my ($out,$err)= runperl_and_capture({}, ['-le',
+ <<'EOF_TEST_CODE'
+ for my $l ("A".."E") {
+ my $pid= fork;
+ if ($pid) {
+ push @pids, $pid;
+ }
+ elsif (!defined $pid) {
+ print "$l:failed fork";
+ } elsif (!$pid) {
+ print "$l:", map { chr(rand(26)+65) } 1..10;
+ exit;
+ }
+ }
+ waitpid $_,0 for @pids;
+EOF_TEST_CODE
+ ]);
+ is($err, "", "No exceptions forking.");
+ my @parts= sort { $a cmp $b } split /\n/, $out;
+ my @want= (
+ "A:KNXDITWWJZ",
+ "B:WDQJGTBJQS",
+ "C:ZGYCCINIHE",
+ "D:UGLGAEXFBP",
+ "E:MQLTNZGZQB"
+ );
+ is("@parts","@want","Works as expected with forks.");
+}
+
+done_testing();