diff --git a/src/tests/AGENTS.md b/src/tests/AGENTS.md index f6dd6eb9..3afd1d56 100644 --- a/src/tests/AGENTS.md +++ b/src/tests/AGENTS.md @@ -15,6 +15,7 @@ Top-level test harness and source-tree tests for ShellSpy/Punk. Tests here exerc - `runtests.tcl` is the primary source-tree test entry point; sublevel `all.tcl` files are a legacy pattern and are not required. - Tests use `tcltest` unless a child AGENTS.md documents a different local harness. - `runtests.tcl` excludes `AGENTS.md` and `*.tcl` helper files when discovering `.test` files. +- `runtests.tcl` defaults tcltest `-tmpdir` (the `makeFile`/`makeDirectory` location) to a fresh directory under the system temp area, deleted before exit, so test helper files never land in the source tree (aborted core exec.test runs previously littered `src/tests`). A `-tmpdir` supplied via `-tcltestoptions` overrides this. Applies to single-process mode; multi-process mode does not yet forward tcltest options to child processes. - The single-process testinterp runs `package prefer latest` so alpha-versioned dev modules (`999999.0a1.0`) are preferred over stable bootsupport/vendored copies on unversioned `package require`. - The testinterp module path includes `src/vendormodules` (and `src/vendormodules_tcl` when present) so vendored dependencies such as `voo` resolve in tests. - Tests should run against source modules and libraries from `src/`, not installed packages or root-level build outputs. diff --git a/src/tests/runtests.tcl b/src/tests/runtests.tcl index 7863de26..9f9ae976 100644 --- a/src/tests/runtests.tcl +++ b/src/tests/runtests.tcl @@ -414,6 +414,27 @@ if {[llength $file_globs] == 0} { dict set tcltestoptions -file $file_globs +#Default tcltest's -tmpdir (makeFile/makeDirectory location) to a fresh directory under the system temp area. +#Without this, tcltest helpers land in the working directory - aborted runs of e.g core exec.test littered +#src/tests with untracked helper files (cat, echo, gorp.file ...). A user-supplied -tmpdir via -tcltestoptions wins. +#Cleaned up (file delete -force) before exit; an aborted run leaves it in the OS temp area rather than the source tree. +set runtests_tmpdir "" +if {![dict exists $opt_tcltestoptions -tmpdir]} { + if {[catch {file tempdir} runtests_tmpdir]} { + #'file tempdir' requires tcl 8.7+ - fall back to env temp + pid subdir for 8.6 + set runtests_tmpdir "" + foreach evar {TMPDIR TEMP TMP} { + if {[info exists ::env($evar)] && [file isdirectory $::env($evar)]} { + set runtests_tmpdir [file join $::env($evar) runtests_tmp_[pid]] + file mkdir $runtests_tmpdir + break + } + } + } + if {$runtests_tmpdir ne ""} { + dict set tcltestoptions -tmpdir $runtests_tmpdir + } +} #puts "tcltestoptions: $tcltestoptions" #puts "file_globs: $file_globs" @@ -801,6 +822,10 @@ if {!$report_json_only} { puts stdout "" } +if {$runtests_tmpdir ne "" && [file isdirectory $runtests_tmpdir]} { + catch {file delete -force $runtests_tmpdir} +} + if {$opt_strict_exit} { if {[dict get $tallydict failed] > 0 || [llength [dict get $tallydict files_with_fails]] > 0} { exit 1