Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 61 additions & 47 deletions stdlib/Test/src/Test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1932,36 +1932,43 @@ function testset_beginend_call(args, tests, source)
$(testsettype)($desc; $options...)
end

# we reproduce the logic of guardseed, but this function
# cannot be used as it changes slightly the semantic of @testset,
# by wrapping the body in a function
local default_rng_orig = copy(default_rng())
local tls_seed_orig = copy(Random.get_tls_seed())
local ts_rng = get_rng(ts)
local tls_seed = isnothing(ts_rng) ? set_rng!(ts, tls_seed_orig) : ts_rng
try
@with_testset ts begin
# default RNG is reset to its state from last `seed!()` to ease reproduce a failed test
copy!(Random.default_rng(), tls_seed)
copy!(Random.get_tls_seed(), Random.default_rng())
let
$(esc(tests))
# Check if this testset should run based on filtering
local testset_id = generate_deterministic_testset_id($(string(source.file)), $(source.line), $desc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean that adding some newlines changes this ID? Or adding new lines to a macro wrapping @testset?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ID just needs to be stable between the discovery and runtime. It doesn't need to be stable otherwise.

Copy link
Contributor

@Seelengrab Seelengrab Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any chance for this ending up in some cache that could cause these to go out of sync, e.g. in a language server?

if should_run_testset_by_id(testset_id)
# we reproduce the logic of guardseed, but this function
# cannot be used as it changes slightly the semantic of @testset,
# by wrapping the body in a function
local default_rng_orig = copy(default_rng())
local tls_seed_orig = copy(Random.get_tls_seed())
local ts_rng = get_rng(ts)
local tls_seed = isnothing(ts_rng) ? set_rng!(ts, tls_seed_orig) : ts_rng
try
@with_testset ts begin
# default RNG is reset to its state from last `seed!()` to ease reproduce a failed test
copy!(Random.default_rng(), tls_seed)
copy!(Random.get_tls_seed(), Random.default_rng())
let
$(esc(tests))
end
end
catch err
err isa InterruptException && rethrow()
# something in the test block threw an error. Count that as an
# error in this test set
trigger_test_failure_break(err)
if is_failfast_error(err)
get_testset_depth() > 0 ? rethrow() : failfast_print()
else
record(ts, Error(:nontest_error, Expr(:tuple), err, Base.current_exceptions(), $(QuoteNode(source)), nothing))
end
finally
copy!(default_rng(), default_rng_orig)
copy!(Random.get_tls_seed(), tls_seed_orig)
ret = finish(ts)
end
catch err
err isa InterruptException && rethrow()
# something in the test block threw an error. Count that as an
# error in this test set
trigger_test_failure_break(err)
if is_failfast_error(err)
get_testset_depth() > 0 ? rethrow() : failfast_print()
else
record(ts, Error(:nontest_error, Expr(:tuple), err, Base.current_exceptions(), $(QuoteNode(source)), nothing))
end
finally
copy!(default_rng(), default_rng_orig)
copy!(Random.get_tls_seed(), tls_seed_orig)
ret = finish(ts)
else
# Skip this testset entirely - don't even create it
ret = nothing
end
ret
end
Expand Down Expand Up @@ -2022,26 +2029,32 @@ function testset_forloop(args, testloop, source)
else
$(testsettype)($desc; $options...)
end
try
@with_testset ts begin
# default RNG is reset to its state from last `seed!()` to ease reproduce a failed test
copy!(Random.default_rng(), tls_seed)
$(esc(tests))
end
catch err
err isa InterruptException && rethrow()
# Something in the test block threw an error. Count that as an
# error in this test set
trigger_test_failure_break(err)
if is_failfast_error(err)
get_testset_depth() > 0 ? rethrow() : failfast_print()
else
record(ts, Error(:nontest_error, Expr(:tuple), err, Base.current_exceptions(), $(QuoteNode(source)), nothing))

# Check if this testset should run based on filtering
local testset_id = generate_deterministic_testset_id($(string(source.file)), $(source.line), $desc)
if should_run_testset_by_id(testset_id)
try
@with_testset ts begin
# default RNG is reset to its state from last `seed!()` to ease reproduce a failed test
copy!(Random.default_rng(), tls_seed)
$(esc(tests))
end
catch err
err isa InterruptException && rethrow()
# Something in the test block threw an error. Count that as an
# error in this test set
trigger_test_failure_break(err)
if is_failfast_error(err)
get_testset_depth() > 0 ? rethrow() : failfast_print()
else
record(ts, Error(:nontest_error, Expr(:tuple), err, Base.current_exceptions(), $(QuoteNode(source)), nothing))
end
finally
push!(arr, finish(ts))
end
finally
copy!(default_rng(), default_rng_orig)
copy!(Random.get_tls_seed(), tls_seed_orig)
push!(arr, finish(ts))
else
# Skip this testset entirely - don't add it to results
# Do nothing instead of pushing a finished empty testset
end
end
quote
Expand Down Expand Up @@ -2474,6 +2487,7 @@ function _check_bitarray_consistency(B::BitArray{N}) where N
return true
end

include("testset_filtering.jl")
include("logging.jl")
include("precompile.jl")

Expand Down
Loading