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

#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.