Skip to content

Commit 08ea2d8

Browse files
authored
@testset: with Xoshiro, restore Random.GLOBAL_SEED (#43188)
A `@testset` is supposed to restore the "global RNG state" as it was before execution (so that they can be re-ordered easily, etc.) Also, before a testset starts, the default RNG is re-seeded with the "global seed" (to help reproduce test failures). Before `Xoshiro` as the default RNG, the "global seed" was stored within a `MersenneTwister` object. It was enough for a testset to copy the default RNG at the start, and copy it back at the end. But now the global seed is stored outside of the RNG, so it should also be restored separately.
1 parent 8c97995 commit 08ea2d8

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

stdlib/Random/src/RNGs.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ copy!(::_GLOBAL_RNG, src::Xoshiro) = copy!(default_rng(), src)
392392
copy(::_GLOBAL_RNG) = copy(default_rng())
393393

394394
GLOBAL_SEED = 0
395+
set_global_seed!(seed) = global GLOBAL_SEED = seed
395396

396397
function seed!(::_GLOBAL_RNG, seed=rand(RandomDevice(), UInt64, 4))
397398
global GLOBAL_SEED = seed

stdlib/Test/src/Test.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,7 @@ function testset_beginend_call(args, tests, source)
13401340
# by wrapping the body in a function
13411341
local RNG = default_rng()
13421342
local oldrng = copy(RNG)
1343+
local oldseed = Random.GLOBAL_SEED
13431344
try
13441345
# RNG is re-seeded with its own seed to ease reproduce a failed test
13451346
Random.seed!(Random.GLOBAL_SEED)
@@ -1353,6 +1354,7 @@ function testset_beginend_call(args, tests, source)
13531354
record(ts, Error(:nontest_error, Expr(:tuple), err, Base.current_exceptions(), $(QuoteNode(source))))
13541355
finally
13551356
copy!(RNG, oldrng)
1357+
Random.set_global_seed!(oldseed)
13561358
pop_testset()
13571359
ret = finish(ts)
13581360
end
@@ -1433,6 +1435,7 @@ function testset_forloop(args, testloop, source)
14331435
local ts
14341436
local RNG = default_rng()
14351437
local oldrng = copy(RNG)
1438+
local oldseed = Random.GLOBAL_SEED
14361439
Random.seed!(Random.GLOBAL_SEED)
14371440
local tmprng = copy(RNG)
14381441
try
@@ -1446,6 +1449,7 @@ function testset_forloop(args, testloop, source)
14461449
push!(arr, finish(ts))
14471450
end
14481451
copy!(RNG, oldrng)
1452+
Random.set_global_seed!(oldseed)
14491453
end
14501454
arr
14511455
end

stdlib/Test/test/runtests.jl

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,29 @@ end
923923
Random.seed!(seed)
924924
@test a == rand()
925925
@test b == rand()
926+
927+
# Even when seed!() is called within a testset A, subsequent testsets
928+
# should start with the same "global RNG state" as what A started with,
929+
# such that the test `refvalue == rand(Int)` below succeeds.
930+
# Currently, this means that Random.GLOBAL_SEED has to be restored,
931+
# in addition to the state of Random.default_rng().
932+
GLOBAL_SEED_orig = Random.GLOBAL_SEED
933+
local refvalue
934+
@testset "GLOBAL_SEED is also preserved (setup)" begin
935+
@test GLOBAL_SEED_orig == Random.GLOBAL_SEED
936+
refvalue = rand(Int)
937+
Random.seed!()
938+
@test GLOBAL_SEED_orig != Random.GLOBAL_SEED
939+
end
940+
@test GLOBAL_SEED_orig == Random.GLOBAL_SEED
941+
@testset "GLOBAL_SEED is also preserved (forloop)" for _=1:3
942+
@test refvalue == rand(Int)
943+
Random.seed!()
944+
end
945+
@test GLOBAL_SEED_orig == Random.GLOBAL_SEED
946+
@testset "GLOBAL_SEED is also preserved (beginend)" begin
947+
@test refvalue == rand(Int)
948+
end
926949
end
927950

928951
@testset "InterruptExceptions #21043" begin
@@ -1280,4 +1303,3 @@ let
12801303
end
12811304
end
12821305
end
1283-

0 commit comments

Comments
 (0)