|
401 | 401 | @test ParallelTestRunner.ID_COUNTER[] == old_id_counter + njobs |
402 | 402 | end |
403 | 403 |
|
| 404 | +# Count direct child processes of current process (for default-worker test). |
| 405 | +# Returns -1 if unsupported so the test can be skipped. |
| 406 | +function _count_child_pids() |
| 407 | + pid = getpid() |
| 408 | + if Sys.isunix() && !isnothing(Sys.which("ps")) |
| 409 | + pids = Int[] |
| 410 | + out = try |
| 411 | + readchomp(`ps -o ppid= -o pid= -A`) |
| 412 | + catch |
| 413 | + return -1 |
| 414 | + end |
| 415 | + lines = split(out, '\n') |
| 416 | + for line in lines |
| 417 | + m = match(r" *(\d+) +(\d+)", line) |
| 418 | + if !isnothing(m) |
| 419 | + if parse(Int, m[1]) == pid |
| 420 | + push!(pids, parse(Int, m[2])) |
| 421 | + end |
| 422 | + end |
| 423 | + end |
| 424 | + # The output of `ps` always contains `ps` itself because it's spawn by |
| 425 | + # the current process, so we subtract one to always exclude it. |
| 426 | + return length(pids) - 1 |
| 427 | + else |
| 428 | + return -1 |
| 429 | + end |
| 430 | +end |
| 431 | + |
| 432 | +# Issue <https://github.com/JuliaTesting/ParallelTestRunner.jl/issues/106>. |
| 433 | +@testset "default workers stopped at end" begin |
| 434 | + # Use default workers (no test_worker) so the framework creates and should stop them. |
| 435 | + # More tests than workers so some tasks finish early and must stop their worker. |
| 436 | + testsuite = Dict( |
| 437 | + "t1" => :(), |
| 438 | + "t2" => :(), |
| 439 | + "t3" => :(), |
| 440 | + "t4" => :(), |
| 441 | + "t5" => :(), |
| 442 | + "t6" => :(), |
| 443 | + ) |
| 444 | + before = _count_child_pids() |
| 445 | + if before < 0 |
| 446 | + # Counting child PIDs not supported on this platform |
| 447 | + @test_broken false |
| 448 | + else |
| 449 | + old_id_counter = ParallelTestRunner.ID_COUNTER[] |
| 450 | + njobs = 2 |
| 451 | + runtests(ParallelTestRunner, ["--jobs=$(njobs)", "--verbose"]; testsuite, stdout=devnull, stderr=devnull) |
| 452 | + @test ParallelTestRunner.ID_COUNTER[] == old_id_counter + njobs |
| 453 | + # Allow a moment for worker processes to exit |
| 454 | + for _ in 1:50 |
| 455 | + sleep(0.1) |
| 456 | + after = _count_child_pids() |
| 457 | + after >= 0 && after <= before && break |
| 458 | + end |
| 459 | + after = _count_child_pids() |
| 460 | + @test after >= 0 |
| 461 | + @test after == before |
| 462 | + end |
| 463 | +end |
| 464 | + |
| 465 | +# Custom workers are handled differently: |
| 466 | +# <https://github.com/JuliaTesting/ParallelTestRunner.jl/pull/107#issuecomment-3980645143>. |
| 467 | +# But we still want to make sure they're terminated at the end. |
| 468 | +@testset "custom workers stopped at end" begin |
| 469 | + testsuite = Dict( |
| 470 | + "a" => :(), |
| 471 | + "b" => :(), |
| 472 | + "c" => :(), |
| 473 | + "d" => :(), |
| 474 | + "e" => :(), |
| 475 | + "f" => :(), |
| 476 | + ) |
| 477 | + procs = Base.Process[] |
| 478 | + procs_lock = ReentrantLock() |
| 479 | + function test_worker(name) |
| 480 | + wrkr = addworker() |
| 481 | + Base.@lock procs_lock push!(procs, wrkr.w.proc) |
| 482 | + return wrkr |
| 483 | + end |
| 484 | + runtests(ParallelTestRunner, Base.ARGS; test_worker, testsuite, stdout=devnull, stderr=devnull) |
| 485 | + @test all(!Base.process_running, procs) |
| 486 | +end |
| 487 | + |
404 | 488 | end |
0 commit comments