Browse Source
The whole pipeline now lives in the zig recipe; Tcl remains the tool exactly
where a tclsh is guaranteed to exist - run by the FRESHLY BUILT suite shell
as build steps:
- New steps (native-host builds): smoke (static shell patchlevel; zip shell
patchlevel + attached tzdata/autoload), tklib / tcllib (their own installers,
batch, -pkg-path as a cached output dir installed into the prefix, + package
smokes incl withdrawn-Tk tooltip), tcllibc (critcl driving zig cc via the
tracked critcl_zig.config, module list parsed from tcllib's version.tcl,
pinned-zig dir prepended to PATH, + accel smoke), test-gate (tools/
test_gate.tcl - the parsed-totals gate vs expected_test_failures.txt,
-Dtestargs passthrough).
- Package landing moves into the recipe proper: thread pkgIndex.tcl
(build_tclthread), tk pkgIndex.tcl (build_tk), and the tclvfs script package
incl .in-template substitution + dll (build_tclvfs_shared
install_tclvfs_package) - all hooked to the install step.
- Step scripts: tools/test_gate.tcl, tools/suite_smoke.tcl, tools/pkg_smoke.tcl
(run under the built shell; assertions live in Tcl).
- Two windows-childproofing findings encoded: built-shell Runs execute the
CACHED artifact (no ../lib/tcl9.0 beside it) so each such Run gets
TCL_LIBRARY pointed at the source tree's script library (the zip smoke
deliberately excluded - its attached library is the thing under test); and
cached (non-side-effect) Runs spawn with stdout IGNORED, leaving the tcl
child without a stdout channel ('can not find channel named "stdout"',
critcl's logging) - such runs capture stdout to give the child a real pipe
while keeping caching.
- suite.tcl: thinned to the fossil dev flow - fetch live checkouts (git kind
now handled in the main loop for critcl's pin), stage the recipe, delegate
to the staged steps (run_zig_steps; 'test' delegates to test-gate). Default
-steps and the bootstrap default grow to the full pipeline short of
test-gate. critcl_zig.config + expected_test_failures.txt join both staging
lists. Docs updated (README two-flow section, sources.config two-surface
header, overlay section); .gitignore learns .zig-cache/ and zig-pkg/ (zig
0.16 extracts fetched packages into zig-pkg/ beside the manifest).
Verified (fossil flow): full pipeline PASS - suite_smoke static+zip, tklib
tooltip:2.0.4 under withdrawn Tk, tcllib md5/sha1/cmdline, tcllibc:2.0 with
md5-critcl-accel:1; 'suite.tcl test -testargs {-file http.test}' delegates to
the gate step (528/519/9/0 GATE PASS).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
12 changed files with 589 additions and 294 deletions
@ -0,0 +1,42 @@
|
||||
#pkg_smoke.tcl (G-102): package-resolution smoke run under a suite-built shell. |
||||
#Requires each named package against the shell's own installed prefix, printing |
||||
#name+version; -gui 1 wraps the requires in a withdrawn Tk root (for tklib |
||||
#packages that need a display); -accel <pkg> additionally asserts the package's |
||||
#critcl accelerator engaged (::<pkg>::accel(critcl) == 1, tcllibc proof). |
||||
#Formerly suite.tcl inline smokes. |
||||
# |
||||
#args: ?-gui 0|1? ?-accel <pkg>? package ?package ...? |
||||
|
||||
proc fail {msg} {puts stderr "pkg_smoke FAIL: $msg"; flush stderr; exit 1} |
||||
|
||||
set gui 0 |
||||
set accel {} |
||||
set pkgs {} |
||||
for {set i 0} {$i < [llength $argv]} {incr i} { |
||||
set a [lindex $argv $i] |
||||
switch -- $a { |
||||
-gui {incr i; set gui [lindex $argv $i]} |
||||
-accel {incr i; set accel [lindex $argv $i]} |
||||
default {lappend pkgs $a} |
||||
} |
||||
} |
||||
if {![llength $pkgs] && $accel eq ""} {fail "no packages given"} |
||||
if {$gui} { |
||||
if {[catch {package require Tk; wm withdraw .} err]} {fail "Tk load failed: $err"} |
||||
} |
||||
set report {} |
||||
foreach pkg $pkgs { |
||||
if {[catch {package require $pkg} ver]} {fail "package require $pkg failed: $ver"} |
||||
lappend report "$pkg:$ver" |
||||
} |
||||
if {$accel ne ""} { |
||||
if {[catch {package require $accel} err]} {fail "package require $accel (accel host) failed: $err"} |
||||
upvar #0 ::${accel}::accel accelarr |
||||
if {![info exists accelarr(critcl)] || !$accelarr(critcl)} { |
||||
fail "critcl accelerator not engaged for $accel (tcllibc not loading?)" |
||||
} |
||||
lappend report "${accel}-critcl-accel:1" |
||||
} |
||||
if {$gui} {catch {destroy .}} |
||||
puts "pkg_smoke OK: [join $report { }]" |
||||
exit 0 |
||||
@ -0,0 +1,26 @@
|
||||
#suite_smoke.tcl (G-102): smoke assertions run under a suite-built shell itself |
||||
#(the shell being smoked executes this script). Formerly suite.tcl inline smokes. |
||||
# |
||||
#args: -mode static|zip -expect <patchlevel> |
||||
# static: interpreter reports the expected patchlevel |
||||
# zip: additionally proves the ATTACHED library works - tzdata reachable |
||||
# (clock format with a named zone) and auto_load present |
||||
|
||||
proc fail {msg} {puts stderr "suite_smoke FAIL: $msg"; flush stderr; exit 1} |
||||
|
||||
array set opt {-mode static -expect {}} |
||||
foreach {k v} $argv { |
||||
if {![info exists opt($k)]} {fail "unknown option '$k'"} |
||||
set opt($k) $v |
||||
} |
||||
if {$opt(-expect) eq ""} {fail "missing -expect <patchlevel>"} |
||||
set pl [info patchlevel] |
||||
if {$pl ne $opt(-expect)} {fail "patchlevel mismatch: got '$pl' want '$opt(-expect)' ([info nameofexecutable])"} |
||||
if {$opt(-mode) eq "zip"} { |
||||
if {[catch {clock format 0 -gmt 0 -format %Z} tz]} {fail "tzdata not reachable from attached library: $tz"} |
||||
if {[llength [info procs auto_load]] != 1} {fail "auto_load missing - attached library init incomplete"} |
||||
puts "suite_smoke OK: $pl (zip: tz=$tz auto=1) [info nameofexecutable]" |
||||
} else { |
||||
puts "suite_smoke OK: $pl [info nameofexecutable]" |
||||
} |
||||
exit 0 |
||||
@ -0,0 +1,71 @@
|
||||
#test_gate.tcl (G-102): run the Tcl core testsuite under THIS interpreter's own |
||||
#shell ([info nameofexecutable] - the suite-built tclsh when driven as the |
||||
#'zig build test-gate' step) and GATE on the parsed totals: all.tcl's exit code |
||||
#does NOT reflect failures, so every failed test must appear in the tracked |
||||
#dispositioned baseline or the gate fails listing the unexplained names. |
||||
#Formerly suite.tcl's 'test' action; suite.tcl now delegates here. |
||||
# |
||||
#args: -testsdir <dir> -baseline <file> -logfile <file> ?-testargs {tcltest args}? |
||||
|
||||
proc fail {msg} {puts stderr "test_gate ERROR: $msg"; flush stderr; exit 1} |
||||
|
||||
array set opt {-testsdir {} -baseline {} -logfile {} -testargs {}} |
||||
foreach {k v} $argv { |
||||
if {![info exists opt($k)]} {fail "unknown option '$k' (expected -testsdir -baseline -logfile -testargs)"} |
||||
set opt($k) $v |
||||
} |
||||
foreach req {-testsdir -baseline -logfile} { |
||||
if {$opt($req) eq ""} {fail "missing required option $req"} |
||||
} |
||||
if {![file isdirectory $opt(-testsdir)]} {fail "no tests dir at $opt(-testsdir) - build first"} |
||||
if {![file exists $opt(-baseline)]} {fail "no baseline file at $opt(-baseline)"} |
||||
|
||||
set exe [info nameofexecutable] |
||||
set logfile [file normalize $opt(-logfile)] |
||||
puts "test_gate: tcl testsuite under $exe [expr {[llength $opt(-testargs)] ? $opt(-testargs) : "(full suite)"}] -> $logfile" |
||||
flush stdout |
||||
set savedpwd [pwd] |
||||
cd $opt(-testsdir) |
||||
catch {exec $exe all.tcl {*}$opt(-testargs) > $logfile 2>@1} |
||||
cd $savedpwd |
||||
|
||||
set f [open $logfile r]; set testout [read $f]; close $f |
||||
if {![regexp {all\.tcl:\s+Total\s+(\d+)\s+Passed\s+(\d+)\s+Skipped\s+(\d+)\s+Failed\s+(\d+)} $testout -> ntotal npassed nskipped nfailed]} { |
||||
fail "no all.tcl totals line found in $logfile - run did not complete" |
||||
} |
||||
puts "test_gate: totals: $ntotal run, $npassed passed, $nskipped skipped, $nfailed failed" |
||||
set failednames {} |
||||
foreach {- tname} [regexp -all -inline -line {^==== (\S+) FAILED} $testout] { |
||||
if {$tname ni $failednames} {lappend failednames $tname} |
||||
} |
||||
#baseline: one test name per line; '#' comments carry the disposition reasons |
||||
set baseline {} |
||||
set f [open $opt(-baseline) r] |
||||
foreach line [split [read $f] \n] { |
||||
set line [string trim $line] |
||||
if {$line eq "" || [string index $line 0] eq "#"} continue |
||||
lappend baseline [lindex $line 0] |
||||
} |
||||
close $f |
||||
set unexplained {} |
||||
foreach tname $failednames { |
||||
if {$tname ni $baseline} {lappend unexplained $tname} |
||||
} |
||||
if {![llength $opt(-testargs)]} { |
||||
#only meaningful for full runs: baseline entries that no longer fail |
||||
set stale {} |
||||
foreach tname $baseline { |
||||
if {$tname ni $failednames} {lappend stale $tname} |
||||
} |
||||
if {[llength $stale]} { |
||||
puts "test_gate: note: [llength $stale] baseline entries did not fail this run (candidates for removal): $stale" |
||||
} |
||||
} |
||||
if {[llength $unexplained]} { |
||||
puts stderr "test_gate GATE FAIL: [llength $unexplained] failed test(s) not in the expected-failure baseline:" |
||||
foreach tname $unexplained {puts stderr " $tname"} |
||||
puts stderr "(full output: $logfile; baseline: $opt(-baseline))" |
||||
exit 1 |
||||
} |
||||
puts "test_gate: GATE PASS ([llength $failednames] failures, all baselined)" |
||||
exit 0 |
||||
Loading…
Reference in new issue