-
Notifications
You must be signed in to change notification settings - Fork 9
Print a completion message when all tests are done #192
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
Changes from all commits
0be51fe
5a92d85
3fbada9
73d1354
0cf46b4
442d68e
b3c6927
96caf0a
f4b27a4
ac30230
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,7 @@ using Test: Test, DefaultTestSet, TestSetException | |
using .Threads: @spawn, nthreads | ||
using Pkg: Pkg | ||
using TestEnv | ||
using Logging | ||
using LoggingExtras | ||
using Logging: current_logger, with_logger | ||
|
||
export runtests, runtestitem | ||
export @testsetup, @testitem | ||
|
@@ -66,6 +65,7 @@ function softscope_all!(@nospecialize ex) | |
end | ||
end | ||
|
||
include("debug.jl") | ||
include("workers.jl") | ||
using .Workers | ||
include("macros.jl") | ||
|
@@ -304,7 +304,7 @@ function runtests( | |
cfg = _Config(; nworkers, nworker_threads, worker_init_expr, test_end_expr, testitem_timeout, testitem_failfast, failfast, retries, logs, report, verbose_results, timeout_profile_wait, memory_threshold, gc_between_testitems) | ||
debuglvl = Int(debug) | ||
if debuglvl > 0 | ||
LoggingExtras.withlevel(LoggingExtras.Debug; verbosity=debuglvl) do | ||
withdebug(debuglvl) do | ||
_runtests(ti_filter, paths′, cfg) | ||
end | ||
else | ||
|
@@ -443,23 +443,24 @@ function _runtests_in_current_env( | |
ti = starting[i] | ||
@spawn begin | ||
with_logger(original_logger) do | ||
manage_worker($w, $proj_name, $testitems, $ti, $cfg) | ||
manage_worker($w, $proj_name, $testitems, $ti, $cfg; worker_num=$i) | ||
end | ||
end | ||
end | ||
end | ||
Test.TESTSET_PRINT_ENABLE[] = true # reenable printing so our `finish` prints | ||
# Let users know if tests are done, and if all of them ran (or if we failed fast). | ||
# Print this above the final report as there might have been other logs printed | ||
# since a failfast-cancellation was printed, but print it ASAP after tests finish | ||
# in case any of the recording/reporting steps have an issue. | ||
print_completion_summary(testitems; failedfast=(cfg.failfast && is_cancelled(testitems))) | ||
record_results!(testitems) | ||
cfg.report && write_junit_file(proj_name, dirname(projectfile), testitems.graph.junit) | ||
if cfg.failfast && is_cancelled(testitems) | ||
# Let users know if not all tests ran. Print this just above the final report as | ||
# there might have been other logs printed since the cancellation was printed. | ||
print_failfast_summary(testitems) | ||
end | ||
@debugv 1 "Calling Test.finish(testitems)" | ||
Test.finish(testitems) # print summary of total passes/failures/errors | ||
finally | ||
Test.TESTSET_PRINT_ENABLE[] = true | ||
# Cleanup test setup logs | ||
@debugv 1 "Cleaning up test setup logs" | ||
foreach(Iterators.filter(endswith(".log"), readdir(RETESTITEMS_TEMP_FOLDER[], join=true))) do logfile | ||
try | ||
# See https://github.com/JuliaTesting/ReTestItems.jl/issues/124 | ||
|
@@ -468,7 +469,9 @@ function _runtests_in_current_env( | |
@debug "Error while attempting to remove $(logfile)" err | ||
end | ||
end | ||
@debugv 1 "Done cleaning up test setup logs" | ||
end | ||
@debugv 1 "DONE" | ||
return nothing | ||
end | ||
|
||
|
@@ -577,16 +580,18 @@ function record_test_error!(testitem, msg, elapsed_seconds::Real=0.0) | |
return testitem | ||
end | ||
|
||
# The provided `worker_num` is only for logging purposes, and not persisted as part of the worker. | ||
function manage_worker( | ||
worker::Worker, proj_name::AbstractString, testitems::TestItems, testitem::Union{TestItem,Nothing}, cfg::_Config, | ||
worker::Worker, proj_name::AbstractString, testitems::TestItems, testitem::Union{TestItem,Nothing}, cfg::_Config; | ||
worker_num::Int | ||
) | ||
ntestitems = length(testitems.testitems) | ||
run_number = 1 | ||
memory_threshold_percent = 100 * cfg.memory_threshold | ||
while testitem !== nothing | ||
ch = Channel{TestItemResult}(1) | ||
if memory_percent() > memory_threshold_percent | ||
@warn "Memory usage ($(Base.Ryu.writefixed(memory_percent(), 1))%) is higher than threshold ($(Base.Ryu.writefixed(memory_threshold_percent, 1))%). Restarting worker process to try to free memory." | ||
@warn "Memory usage ($(Base.Ryu.writefixed(memory_percent(), 1))%) is higher than threshold ($(Base.Ryu.writefixed(memory_threshold_percent, 1))%). Restarting process for worker $worker_num to try to free memory." | ||
terminate!(worker) | ||
wait(worker) | ||
worker = robust_start_worker(proj_name, cfg.nworker_threads, cfg.worker_init_expr, ntestitems) | ||
|
@@ -642,7 +647,7 @@ function manage_worker( | |
close(timer) | ||
end | ||
catch e | ||
@debugv 2 "Error" exception=e | ||
@debugv 2 "Error: $e" | ||
# Handle the exception | ||
if e isa TimeoutException | ||
if cfg.timeout_profile_wait > 0 | ||
|
@@ -684,7 +689,7 @@ function manage_worker( | |
run_number = 1 | ||
else | ||
run_number += 1 | ||
@info "Retrying $(repr(testitem.name)) on a new worker process. Run=$run_number." | ||
@info "Retrying $(repr(testitem.name)) on a new worker $worker_num process. Run=$run_number." | ||
end | ||
# The worker was terminated, so replace it unless there are no more testitems to run | ||
if testitem !== nothing | ||
|
@@ -694,7 +699,9 @@ function manage_worker( | |
continue | ||
end | ||
end | ||
@info "All tests on worker $worker_num completed. Closing $worker." | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be helpful to add the number of tests this worker ran on this line? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 nice suggestion There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
close(worker) | ||
@debugv 1 "Worker $worker_num closed: $(worker)" | ||
return nothing | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
DEBUG_LEVEL::Int = 0 | ||
|
||
function setdebug!(level::Int) | ||
global DEBUG_LEVEL = level | ||
return nothing | ||
end | ||
|
||
""" | ||
withdebug(level::Int) do | ||
func() | ||
end | ||
""" | ||
function withdebug(f, level::Int) | ||
old = DEBUG_LEVEL | ||
try | ||
setdebug!(level) | ||
f() | ||
finally | ||
setdebug!(old) | ||
end | ||
end | ||
|
||
""" | ||
@debugv 1 "msg" | ||
""" | ||
macro debugv(level::Int, messsage) | ||
quote | ||
if DEBUG_LEVEL >= $level | ||
_full_file = $String($(QuoteNode(__source__.file))) | ||
_file = $last($splitdir(_full_file)) | ||
_line = $(QuoteNode(__source__.line)) | ||
msg = $(esc(messsage)) | ||
$print("DEBUG @ $(_file):$(_line) | $msg\n") | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,7 +73,7 @@ end | |
function terminate!(w::Worker, from::Symbol=:manual) | ||
already_terminated = @atomicswap :monotonic w.terminated = true | ||
if !already_terminated | ||
@debug "terminating worker $(w.pid) from $from" | ||
@debug "terminating $(w) from $(from)" | ||
end | ||
wte = WorkerTerminatedException(w) | ||
@lock w.lock begin | ||
|
@@ -114,7 +114,7 @@ end | |
# Called when timeout_profile_wait is non-zero. | ||
function trigger_profile(w::Worker, timeout_profile_wait, from::Symbol=:manual) | ||
if !Sys.iswindows() | ||
@debug "sending profile request to worker $(w.pid) from $from" | ||
@debug "sending profile request to $(w) from $(from)" | ||
if Sys.islinux() | ||
kill(w.process, 10) # SIGUSR1 | ||
elseif Sys.isbsd() | ||
|
@@ -128,13 +128,15 @@ end | |
# gracefully terminate a worker by sending a shutdown message | ||
# and waiting for the other tasks to perform worker shutdown | ||
function Base.close(w::Worker) | ||
@debug "closing $(w)" | ||
if !w.terminated && isopen(w.socket) | ||
req = Request(Symbol(), :(), rand(UInt64), true) | ||
@lock w.lock begin | ||
serialize(w.socket, req) | ||
flush(w.socket) | ||
end | ||
end | ||
@debug "waiting for $(w) to terminate" | ||
wait(w) | ||
return | ||
end | ||
|
@@ -231,7 +233,7 @@ function redirect_worker_output(io::IO, w::Worker, fn, proc, ev::Threads.Event) | |
end | ||
end | ||
catch e | ||
# @error "Error redirecting worker output $(w.pid)" exception=(e, catch_backtrace()) | ||
# @error "Error redirecting $(w) output" exception=(e, catch_backtrace()) | ||
terminate!(w, :redirect_worker_output) | ||
e isa EOFError || e isa Base.IOError || rethrow() | ||
finally | ||
|
@@ -250,13 +252,13 @@ function process_responses(w::Worker, ev::Threads.Event) | |
while isopen(w.socket) && !w.terminated | ||
# get the next Response from the worker | ||
r = deserialize(w.socket) | ||
@assert r isa Response "Received invalid response from worker $(w.pid): $(r)" | ||
# println("Received response $(r) from worker $(w.pid)") | ||
@assert r isa Response "Received invalid response from $(w): $(r)" | ||
# println("Received response $(r) from $(w)") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leaving in commented code? |
||
@lock lock begin | ||
@assert haskey(reqs, r.id) "Received response for unknown request $(r.id) from worker $(w.pid)" | ||
@assert haskey(reqs, r.id) "Received response for unknown request $(r.id) from $(w)" | ||
# look up the Future for this request | ||
fut = pop!(reqs, r.id) | ||
@assert !isready(fut.value) "Received duplicate response for request $(r.id) from worker $(w.pid)" | ||
@assert !isready(fut.value) "Received duplicate response for request $(r.id) from $(w)" | ||
if r.error !== nothing | ||
# this allows rethrowing the exception from the worker to the caller | ||
close(fut.value, r.error) | ||
|
@@ -266,7 +268,7 @@ function process_responses(w::Worker, ev::Threads.Event) | |
end | ||
end | ||
catch e | ||
# @error "Error processing responses from worker $(w.pid)" exception=(e, catch_backtrace()) | ||
# @error "Error processing responses from $(w)" exception=(e, catch_backtrace()) | ||
terminate!(w, :process_responses) | ||
e isa EOFError || e isa Base.IOError || rethrow() | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, so @Drvi this would be maybe too late already, since we hang before shutting down the workers?
Maybe we actually just want a log in
manage_worker
, here?:ReTestItems.jl/src/ReTestItems.jl
Line 695 in e9b7730
We could basically say
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added. I just added a log for each worker, so they don't have to coordinate to know if they're the last worker to complete, and also because i suppose any of them could be the one to hang here.