Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: add a "resilient" option to run all tests unconditionally #23589

Merged
merged 7 commits into from
Sep 21, 2017
Merged
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
Next Next commit
add a "resilient" option to run all tests unconditionally
Previously, this was the default: even if one test fails, all
remaining tests are run nonetheless.
Now this requires to pass the "--resilient" option to "test/runtests.jl"
(or `resilient=true` to the `runtest` function); the new default
is to stop running tests as soon as possible when there is one failure.
  • Loading branch information
rfourquet committed Sep 9, 2017
commit f6b24694236d6a61e9850e8f17ea17d055e9e346
10 changes: 7 additions & 3 deletions base/interactiveutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -700,15 +700,19 @@ end
# testing

"""
runtests([tests=["all"] [, numcores=ceil(Int, Sys.CPU_CORES / 2) ]])
Base.runtests(tests=["all"], numcores=ceil(Int, Sys.CPU_CORES / 2);
resilient=false)

Run the Julia unit tests listed in `tests`, which can be either a string or an array of
strings, using `numcores` processors. (not exported)
strings, using `numcores` processors.
If one test fails, all remaining tests will be discarded, unless resilient is `true`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe state here explicitly that if resilient = true all remaining tests in other files will be run?

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, will clarify.

"""
function runtests(tests = ["all"], numcores = ceil(Int, Sys.CPU_CORES / 2))
function runtests(tests = ["all"], numcores = ceil(Int, Sys.CPU_CORES / 2);
resilient=false)
if isa(tests,AbstractString)
tests = split(tests)
end
resilient && push!(tests, "--resilient")
ENV2 = copy(ENV)
ENV2["JULIA_CPU_CORES"] = "$numcores"
try
Expand Down
13 changes: 9 additions & 4 deletions test/choosetests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

@doc """

`tests, net_on = choosetests(choices)` selects a set of tests to be
`tests, net_on, resilient = choosetests(choices)` selects a set of tests to be
run. `choices` should be a vector of test names; if empty or set to
`["all"]`, all tests are selected.

This function also supports "test collections": specifically, "linalg"
refers to collections of tests in the correspondingly-named
directories.

Upon return, `tests` is a vector of fully-expanded test names, and
`net_on` is true if networking is available (required for some tests).
Upon return, `tests` is a vector of fully-expanded test names,
`net_on` is true if networking is available (required for some tests),
and `resilient` is true if all tests should be run unconditionally
(.i.e. even when some of them fail).
""" ->
function choosetests(choices = [])
testnames = [
Expand Down Expand Up @@ -51,11 +53,14 @@ function choosetests(choices = [])

tests = []
skip_tests = []
resilient = false

for (i, t) in enumerate(choices)
if t == "--skip"
skip_tests = choices[i + 1:end]
break
elseif t == "--resilient"
resilient = true
else
push!(tests, t)
end
Expand Down Expand Up @@ -168,5 +173,5 @@ function choosetests(choices = [])

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

tests, net_on
tests, net_on, resilient
end
20 changes: 14 additions & 6 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ using Base.Test
include("choosetests.jl")
include("testenv.jl")

tests, net_on = choosetests(ARGS)
tests, net_on, resilient = choosetests(ARGS)
tests = unique(tests)

const max_worker_rss = if haskey(ENV, "JULIA_TEST_MAXRSS_MB")
Expand Down Expand Up @@ -33,6 +33,7 @@ cd(dirname(@__FILE__)) do
n > 1 && addprocs_with_testenv(n)
BLAS.set_num_threads(1)
end
skipped = 0

@everywhere include("testdefs.jl")

Expand All @@ -59,14 +60,18 @@ cd(dirname(@__FILE__)) do
resp = [e]
end
push!(results, (test, resp))
if resp[1] isa Exception || resp[end] > max_worker_rss
if resp[1] isa Exception
Copy link
Contributor

Choose a reason for hiding this comment

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

sorry if this is stupid but why can't this be if resp[1] isa Exception && !resilient? Since the next condition is an elseif anyway?

Copy link
Member Author

@rfourquet rfourquet Sep 6, 2017

Choose a reason for hiding this comment

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

No problem! If resp[1] isa Exception but resilient == true, then the condition in the elseif would be tested, which is invalid because then resp[end] == res[1] is an exception object which can't be compared as an Int.

if !resilient
skipped = length(tests)
empty!(tests)
end
elseif resp[end] > max_worker_rss
if n > 1
rmprocs(wrkr, waitfor=30)
p = addprocs_with_testenv(1)[1]
remotecall_fetch(include, p, "testdefs.jl")
else
# single process testing, bail if mem limit reached
resp[1] isa Exception || error("Halting tests. Memory limit reached : $resp > $max_worker_rss")
else # single process testing
error("Halting tests. Memory limit reached : $resp > $max_worker_rss")
end
end
if !isa(resp[1], Exception)
Expand Down Expand Up @@ -181,7 +186,10 @@ cd(dirname(@__FILE__)) do
if !o_ts.anynonpass
println(" \033[32;1mSUCCESS\033[0m")
else
println(" \033[31;1mFAILURE\033[0m")
println(" \033[31;1mFAILURE\033[0m\n")
skipped > 0 &&
println("$skipped test", skipped > 1 ? "s were" : " was",
""" skipped due to failure (use the "resilient" option to run all tests unconditionally)\n""")
Base.Test.print_test_errors(o_ts)
throw(Test.FallbackTestSetException("Test run finished with errors"))
end
Expand Down