Skip to content

Commit 736e13e

Browse files
committed
enable seeding of GLOBAL_RNG when running tests
1 parent f2fd1f8 commit 736e13e

File tree

4 files changed

+33
-17
lines changed

4 files changed

+33
-17
lines changed

base/interactiveutil.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,19 +697,23 @@ end
697697

698698
"""
699699
Base.runtests(tests=["all"], numcores=ceil(Int, Sys.CPU_CORES / 2);
700-
exit_on_error=false)
700+
exit_on_error=false, [seed])
701701
702702
Run the Julia unit tests listed in `tests`, which can be either a string or an array of
703703
strings, using `numcores` processors. If `exit_on_error` is `false`, when one test
704704
fails, all remaining tests in other files will still be run; they are otherwise discarded,
705705
when `exit_on_error == true`.
706+
If a seed is provided via the keyword argument, it is used to seed the
707+
global RNG in the context where the tests are run; otherwise the seed is chosen randomly.
706708
"""
707709
function runtests(tests = ["all"], numcores = ceil(Int, Sys.CPU_CORES / 2);
708-
exit_on_error=false)
710+
exit_on_error=false,
711+
seed::Union{BitInteger,Void}=nothing)
709712
if isa(tests,AbstractString)
710713
tests = split(tests)
711714
end
712715
exit_on_error && push!(tests, "--exit-on-error")
716+
seed != nothing && push!(tests, "--seed=0x$(hex(seed % UInt128))") # cast to UInt128 to avoid a minus sign
713717
ENV2 = copy(ENV)
714718
ENV2["JULIA_CPU_CORES"] = "$numcores"
715719
try

test/choosetests.jl

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,29 @@
22

33
@doc """
44
5-
`tests, net_on, exit_on_error = choosetests(choices)` selects a set of tests to be
5+
`tests, net_on, exit_on_error, seed = choosetests(choices)` selects a set of tests to be
66
run. `choices` should be a vector of test names; if empty or set to
77
`["all"]`, all tests are selected.
88
99
This function also supports "test collections": specifically, "linalg"
1010
refers to collections of tests in the correspondingly-named
1111
directories.
1212
13-
Upon return, `tests` is a vector of fully-expanded test names,
14-
`net_on` is true if networking is available (required for some tests),
15-
and `exit_on_error` is true if an error in one test should cancel
16-
remaining tests to be run (otherwise, all tests are run unconditionally).
17-
18-
Two options can be passed to `choosetests` by including a special token
19-
in the `choices` argument: "--skip", which makes all tests coming after
20-
be skipped, and "--exit-on-error" which sets the value of `exit_on_error`.
13+
Upon return:
14+
- `tests` is a vector of fully-expanded test names,
15+
- `net_on` is true if networking is available (required for some tests),
16+
- `exit_on_error` is true if an error in one test should cancel
17+
remaining tests to be run (otherwise, all tests are run unconditionally),
18+
- `seed` is a seed which will be used to initialize the global RNG for each
19+
test to be run.
20+
21+
Three options can be passed to `choosetests` by including a special token
22+
in the `choices` argument:
23+
- "--skip", which makes all tests coming after be skipped,
24+
- "--exit-on-error" which sets the value of `exit_on_error`,
25+
- "--seed=SEED", which sets the value of `seed` to `SEED`
26+
(parsed as an `UInt128`); `seed` is otherwise initialized randomly.
27+
This option can be used to reproduce failed tests.
2128
""" ->
2229
function choosetests(choices = [])
2330
testnames = [
@@ -58,13 +65,16 @@ function choosetests(choices = [])
5865
tests = []
5966
skip_tests = []
6067
exit_on_error = false
68+
seed = rand(RandomDevice(), UInt128)
6169

6270
for (i, t) in enumerate(choices)
6371
if t == "--skip"
6472
skip_tests = choices[i + 1:end]
6573
break
6674
elseif t == "--exit-on-error"
6775
exit_on_error = true
76+
elseif startswith(t, "--seed=")
77+
seed = parse(UInt128, t[8:end])
6878
else
6979
push!(tests, t)
7080
end
@@ -177,5 +187,5 @@ function choosetests(choices = [])
177187

178188
filter!(x -> !(x in skip_tests), tests)
179189

180-
tests, net_on, exit_on_error
190+
tests, net_on, exit_on_error, seed
181191
end

test/runtests.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using Test
44
include("choosetests.jl")
55
include("testenv.jl")
66

7-
tests, net_on, exit_on_error = choosetests(ARGS)
7+
tests, net_on, exit_on_error, seed = choosetests(ARGS)
88
tests = unique(tests)
99

1010
const max_worker_rss = if haskey(ENV, "JULIA_TEST_MAXRSS_MB")
@@ -55,7 +55,7 @@ cd(dirname(@__FILE__)) do
5555
local resp
5656
wrkr = p
5757
try
58-
resp = remotecall_fetch(runtests, wrkr, test)
58+
resp = remotecall_fetch(runtests, wrkr, test; seed=seed)
5959
catch e
6060
resp = [e]
6161
end
@@ -105,7 +105,7 @@ cd(dirname(@__FILE__)) do
105105
n > 1 && print("\tFrom worker 1:\t")
106106
local resp
107107
try
108-
resp = eval(Expr(:call, () -> runtests(t))) # runtests is defined by the include above
108+
resp = eval(Expr(:call, () -> runtests(t, seed=seed))) # runtests is defined by the include above
109109
catch e
110110
resp = [e]
111111
end
@@ -188,7 +188,8 @@ cd(dirname(@__FILE__)) do
188188
else
189189
println(" \033[31;1mFAILURE\033[0m\n")
190190
skipped > 0 &&
191-
println("$skipped test", skipped > 1 ? "s were" : " was", " skipped due to failure.\n")
191+
println("$skipped test", skipped > 1 ? "s were" : " was", " skipped due to failure.")
192+
println("The global RNG seed was 0x$(hex(seed)).\n")
192193
Test.print_test_errors(o_ts)
193194
throw(Test.FallbackTestSetException("Test run finished with errors"))
194195
end

test/testdefs.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
using Test
44

5-
function runtests(name, isolate=true)
5+
function runtests(name, isolate=true; seed=nothing)
66
old_print_setting = Test.TESTSET_PRINT_ENABLE[]
77
Test.TESTSET_PRINT_ENABLE[] = false
88
try
@@ -17,6 +17,7 @@ function runtests(name, isolate=true)
1717
@eval(m, using Test)
1818
ex = quote
1919
@timed @testset $"$name" begin
20+
srand($seed)
2021
include($"$name.jl")
2122
end
2223
end

0 commit comments

Comments
 (0)