You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
4.7 KiB
84 lines
4.7 KiB
#child_test_runner.tcl - child-process bootstrap for src/tests/runtests.tcl multi-process mode |
|
#(-tcltestoptions {-singleproc 0}). |
|
#Invoked as: <tcl_interpreter> child_test_runner.tcl <payloadfile> <testfile> ?<childtmpdir>? |
|
#The payload file is generated per run by runtests.tcl and applies the parent-computed test |
|
#environment in the singleproc-testinterp order: package prefer latest, tcl::tm test paths, |
|
#auto_path, modpod 'package ifneeded' definitions, and the base tcltest options in |
|
#::runtests_child_tcltestoptions. |
|
#The optional childtmpdir argument overrides tcltest -tmpdir per child (parallel scheduling); |
|
#empty/absent means the shared -tmpdir carried in the payload options is used. |
|
#Exit codes: 0 = test file ran to completion (tcltest failures are reported via the tcltest |
|
#output stream, not the exit code - matching tcltest single-file semantics); nonzero = the test |
|
#file (or this bootstrap) died, which runtests.tcl classifies as a file-level failure with the |
|
#stderr tail surfaced; 98 = bootstrap usage/environment error. |
|
#Not a test suite: runtests.tcl discovery excludes *.tcl under src/tests. |
|
|
|
#Initialize process-level clock/timezone state while the DEFAULT module paths are still in place. |
|
#The first script-level 'clock format' pulls in msgcat (and tzdata) from the runtime's own module |
|
#paths; the payload wipes those paths and nothing under the test module paths supplies msgcat. |
|
#The singleproc testinterp is shielded from this only because the runtests parent process uses |
|
#'clock format' under default paths before running test files (process-wide C-level caches) - a |
|
#fresh child process must warm up explicitly or e.g zipper.test fails with |
|
#"can't find package msgcat" out of clock format. |
|
clock format [clock seconds] |
|
|
|
lassign $argv payloadfile testfile childtmpdir |
|
if {$payloadfile eq "" || ![file exists $payloadfile]} { |
|
puts stderr "child_test_runner.tcl: payload file not found: '$payloadfile'" |
|
exit 98 |
|
} |
|
if {$testfile eq ""} { |
|
puts stderr "child_test_runner.tcl: no test file supplied" |
|
exit 98 |
|
} |
|
set testfile [file normalize $testfile] |
|
if {![file exists $testfile]} { |
|
puts stderr "child_test_runner.tcl: test file not found: '$testfile'" |
|
exit 98 |
|
} |
|
|
|
source $payloadfile |
|
|
|
if {![info exists ::runtests_child_tcltestoptions]} { |
|
puts stderr "child_test_runner.tcl: payload did not define ::runtests_child_tcltestoptions" |
|
exit 98 |
|
} |
|
set tcltestoptions $::runtests_child_tcltestoptions |
|
#-testdir is per test file (mirrors the per-file -testdir the runtests loop sets in singleproc mode) |
|
dict set tcltestoptions -testdir [file dirname $testfile] |
|
if {$childtmpdir ne ""} { |
|
dict set tcltestoptions -tmpdir $childtmpdir |
|
} |
|
|
|
#mirror the singleproc testinterp setup: ::argv holds the tcltest options and tcltest is not |
|
#package required until ::argv is in place (see the note at the bottom of runtests.tcl - |
|
#tcltest examines ::argv itself). The explicit tcltest::configure call below also disarms |
|
#tcltest's argv auto-processing traces, so the options cannot be double-applied. |
|
set ::argv0 $testfile |
|
set ::argv $tcltestoptions |
|
set ::argc [llength $tcltestoptions] |
|
package require tcltest |
|
tcltest::configure {*}$tcltestoptions |
|
|
|
#Lean children (2026-07-19 cleanup): the shellrun preload + no-op runx warmup that |
|
#previously mirrored the singleproc testinterp here were removed after the suites' |
|
#implicit punk::* dependencies were made explicit (17 files gained package require lines |
|
#per the existing src/tests/AGENTS.md contract; result parity re-verified with |
|
#scriptlib/developer/runtests_parity.tcl - the same tool that originally pinpointed the |
|
#implicit-dependency files, first as 17 files / 97 tests without shellrun, then 7 files / |
|
#31 tests without the runx-execution punk::lib pull). Children now load only tcltest plus |
|
#whatever each test file declares. The singleproc testinterp still preloads shellrun, but |
|
#as the RUNNER's capture mechanism (runx -tcl sourcing) - not a dependency any test may |
|
#rely on. |
|
#UDP watch-mode note (PUNK_TEST_UDPTEE): no interaction with this leanness today - the |
|
#parent relays child output at file granularity through its own log workers; children |
|
#inherit the env var but nothing here consumes it. If live per-child streaming is ever |
|
#added, make it CONDITIONAL: when env(PUNK_TEST_UDPTEE) is set, either reinstate shellrun |
|
#here and source via 'shellrun::runx -teelog {...} -tcl' (watched children opt into the |
|
#load cost, unwatched children stay lean - symmetric with the watch-gated worker-thread |
|
#cleanup in runtests.tcl), or forward lines over a bare tcludp socket without the shellrun |
|
#stack. |
|
|
|
source $testfile |
|
#natural end-of-script exit: code 0. An uncaught error from the test file propagates, prints |
|
#errorInfo to stderr and exits nonzero - runtests.tcl reports that as a file-level failure.
|
|
|