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.
550 lines
25 KiB
550 lines
25 KiB
package require tcltest |
|
|
|
#G-119: behaviour tests for the punk-runtime freshness verdict - the stated |
|
#relationship between the ACTIVE runtime and the SERVER DEFAULT |
|
#(current/ahead/behind/incomparable) - against a FIXTURE punkbin server: a |
|
#child-process http file server (testsupport/httpfixture.tcl) serves a crafted |
|
#punkbin layout (defaults.txt, <platform>/sha1sums.txt, artifacts + metadata |
|
#tomls) and the PUNKBIN_URL override points both payloads at it. |
|
# |
|
#Both payloads are exercised and their verdict lines compared (parity clause): |
|
# - powershell payload: the committed bin/punk-runtime.cmd staged into a |
|
# tempdir and driven via cmd.exe (the wrap-pinned windows launch path) |
|
# - bash payload: src/scriptapps/bin/punk-runtime.bash staged beside it and |
|
# driven directly via a probed msys/git bash (uname MINGW*/MSYS*): on |
|
# windows the polyglot routes unix shells to the powershell payload (win32 |
|
# nextshell), so the bash payload is executed directly - the same direct |
|
# drive the G-059 WSL suite uses on real linux |
|
# |
|
#All execution happens in a tcltest tempdir staging area against a fixture |
|
#platform folder (testplat-x86_64) - the real bin/runtime store and the real |
|
#punkbin server are never touched. |
|
# |
|
#Covered (G-119 acceptance): |
|
# - active materialized from r2, server default r1 -> 'list -remote' prints an |
|
# explicit AHEAD verdict naming both revisions |
|
# - active r1, default r2 -> BEHIND verdict plus fetch+use update guidance |
|
# - active == default -> the existing '(= server default)' annotation, and no |
|
# freshness lines |
|
# - pre-family active (no toml, no -r<N> name): stated no-revision-basis note; |
|
# hash-identity naming (with revision verdict) when its sha1 VALUE-matches a |
|
# server artifact |
|
# - a no-name fetch prints a one-line active-vs-default note when they diverge |
|
# - ps1/bash parity: identical 'freshness:' lines from both payloads |
|
# - (bash-side extra) different-series incomparable verdict; fetch-mode BEHIND |
|
# note with inline activation hint |
|
# |
|
#NOTE for agents: bin/punk-runtime.cmd is GENERATED - fix the payloads under |
|
#src/scriptapps/bin/ and re-wrap (see bin/AGENTS.md); the roundtrip pin lives in |
|
#src/tests/modules/punk/mix/testsuites/scriptwrap/runtimecmd_roundtrip.test. |
|
|
|
namespace eval ::testspace { |
|
namespace import ::tcltest::* |
|
variable common { |
|
set result "" |
|
} |
|
|
|
variable testdir [file dirname [file normalize [info script]]] |
|
#<projectroot>/src/tests/shell/testsuites/binscripts -> src/tests is 3 levels up |
|
variable testsroot [file normalize [file join $testdir .. .. ..]] |
|
variable projectroot [file normalize [file join $testsroot .. ..]] |
|
|
|
variable target [file join $projectroot bin punk-runtime.cmd] |
|
variable bashsource [file join $projectroot src scriptapps bin punk-runtime.bash] |
|
testConstraint iswindows [expr {$::tcl_platform(platform) eq "windows"}] |
|
testConstraint haveruntimecmd [file exists $target] |
|
testConstraint havebashsource [file exists $bashsource] |
|
testConstraint havecertutil [expr {[auto_execok certutil] ne ""}] |
|
|
|
#msys/git bash probe: a WINDOWS bash whose uname reports MINGW*/MSYS* and |
|
#which carries curl + sha1sum (the payload's fetch/list dependencies). |
|
#Git-for-Windows locations are probed before PATH bash - PATH may resolve |
|
#the WSL System32 bash (uname Linux), which cannot reach a 127.0.0.1 |
|
#fixture server under WSL2 networking and is rejected. |
|
proc find_msys_bash {} { |
|
set candidates {} |
|
foreach c [list \ |
|
{C:/Program Files/Git/bin/bash.exe} \ |
|
{C:/Program Files/Git/usr/bin/bash.exe} \ |
|
{C:/msys64/usr/bin/bash.exe}] { |
|
if {[file exists $c]} { lappend candidates $c } |
|
} |
|
set pathbash [lindex [auto_execok bash] 0] |
|
if {$pathbash ne ""} { lappend candidates $pathbash } |
|
foreach c $candidates { |
|
if {![catch {exec -- $c -c "uname -s" << "" 2>@1} un]} { |
|
set un [string trim $un] |
|
if {[string match "MINGW*" $un] || [string match "MSYS*" $un]} { |
|
if {![catch {exec -- $c -c "command -v curl >/dev/null && command -v sha1sum >/dev/null" << "" 2>@1}]} { |
|
return $c |
|
} |
|
} |
|
} |
|
} |
|
return "" |
|
} |
|
variable msysbash "" |
|
if {[testConstraint iswindows] && [testConstraint havebashsource]} { |
|
set msysbash [find_msys_bash] |
|
} |
|
testConstraint msysbash [expr {$msysbash ne ""}] |
|
|
|
proc writefile_raw {path content} { |
|
set fd [open $path w] |
|
fconfigure $fd -translation binary |
|
puts -nonewline $fd $content |
|
close $fd |
|
} |
|
#sha1 via certutil (windows-native, no package dependency in the testinterp); |
|
#tolerates both contiguous and space-grouped hash output forms |
|
proc sha1_of_file {path} { |
|
set out [exec -- {*}[auto_execok certutil] -hashfile [file nativename $path] SHA1 << "" 2>@1] |
|
foreach ln [split $out \n] { |
|
set compact [string map {" " ""} [string trim $ln]] |
|
if {[regexp {^[0-9a-fA-F]{40}$} $compact]} { |
|
return [string tolower $compact] |
|
} |
|
} |
|
error "no sha1 parsed from certutil output: $out" |
|
} |
|
|
|
#--- fixture punkbin layout (server side) -------------------------------------- |
|
variable plat testplat-x86_64 |
|
variable artifacts [dict create \ |
|
fakert-alpha-r1.exe "FAKERT alpha revision one payload 1111\n" \ |
|
fakert-alpha-r2.exe "FAKERT alpha revision two payload 2222\n" \ |
|
fakert-beta-r1.exe "FAKERT beta revision one payload 3333\n" \ |
|
prefam.exe "PREFAM legacy runtime payload 4444\n"] |
|
proc artifact_toml {name rev} { |
|
variable plat |
|
set l {} |
|
lappend l "# punkbin artifact record (test fixture)" |
|
lappend l "schema = \"1\"" |
|
lappend l "name = \"$name\"" |
|
lappend l "revision = $rev" |
|
lappend l "target = \"$plat\"" |
|
lappend l "variant = \"punk\"" |
|
lappend l "tcl_patchlevel = \"9.0.5\"" |
|
return "[join $l \n]\n" |
|
} |
|
|
|
variable serverroot "" |
|
variable stagedir "" |
|
variable serverchan "" |
|
variable baseurl "" |
|
variable saved_env [dict create] |
|
variable fixtureok 0 |
|
|
|
proc server_start {} { |
|
variable serverroot |
|
variable serverchan |
|
variable baseurl |
|
variable testsroot |
|
set helper [file join $testsroot testsupport httpfixture.tcl] |
|
if {![file exists $helper]} { return 0 } |
|
if {[catch {open |[list [info nameofexecutable] $helper $serverroot] r+} chan]} { |
|
return 0 |
|
} |
|
chan configure $chan -blocking 1 -buffering line |
|
set line [gets $chan] |
|
if {[regexp {^PORT (\d+)$} $line -> p]} { |
|
set serverchan $chan |
|
set baseurl "http://127.0.0.1:$p" |
|
return 1 |
|
} |
|
catch {close $chan} |
|
return 0 |
|
} |
|
proc server_stop {} { |
|
variable serverchan |
|
if {$serverchan ne ""} { |
|
#closing the pipe EOFs the child's stdin - it exits on that |
|
catch {close $serverchan} |
|
set serverchan "" |
|
} |
|
} |
|
|
|
#server-side curated default (a punkbin release decision in real life) |
|
proc set_default {name} { |
|
variable serverroot |
|
variable plat |
|
writefile_raw [file join $serverroot defaults.txt] "# test fixture defaults\n$plat $name\n" |
|
} |
|
|
|
#--- local staging (the payloads' script dir + runtime store) ------------------ |
|
proc reset_stage {} { |
|
variable stagedir |
|
variable plat |
|
file delete -force [file join $stagedir runtime] |
|
file mkdir [file join $stagedir runtime $plat] |
|
} |
|
proc stage_file {name content} { |
|
variable stagedir |
|
variable plat |
|
writefile_raw [file join $stagedir runtime $plat $name] $content |
|
} |
|
proc set_active {name} { |
|
variable stagedir |
|
variable plat |
|
writefile_raw [file join $stagedir runtime $plat active.toml] "active = \"$name\"\n" |
|
} |
|
#what 'use <artifact>' produces: working-name byte copy of the artifact with the |
|
#artifact's metadata toml beside it under the working root name, selected active |
|
proc stage_materialized {working artifact rev} { |
|
variable artifacts |
|
stage_file $working [dict get $artifacts $artifact] |
|
set root [file rootname $working] |
|
stage_file $root.toml [artifact_toml $artifact $rev] |
|
set_active $working |
|
} |
|
|
|
#--- payload drivers ------------------------------------------------------------ |
|
#powershell payload via the wrap-pinned windows path: cmd.exe /c <staged .cmd> |
|
proc run_cmdroute {args} { |
|
variable stagedir |
|
set comspec [expr {[info exists ::env(ComSpec)] ? $::env(ComSpec) : "cmd.exe"}] |
|
set cmdfile [file nativename [file join $stagedir punk-runtime.cmd]] |
|
set output "" |
|
set code 0 |
|
if {[catch {exec -- $comspec /c $cmdfile {*}$args << "" 2>@1} output opts]} { |
|
set ec [dict get $opts -errorcode] |
|
if {[lindex $ec 0] eq "CHILDSTATUS"} { |
|
set code [lindex $ec 2] |
|
} else { |
|
set code -1 |
|
} |
|
} |
|
return [dict create exit $code output $output] |
|
} |
|
#bash payload driven directly under msys bash from the staging dir |
|
proc run_bashroute {args} { |
|
variable stagedir |
|
variable msysbash |
|
set sdir [string map {\\ /} $stagedir] |
|
set script "cd '$sdir' && ./punk-runtime.bash" |
|
foreach a $args { append script " $a" } |
|
set output "" |
|
set code 0 |
|
if {[catch {exec -- $msysbash -c $script << "" 2>@1} output opts]} { |
|
set ec [dict get $opts -errorcode] |
|
if {[lindex $ec 0] eq "CHILDSTATUS"} { |
|
set code [lindex $ec 2] |
|
} else { |
|
set code -1 |
|
} |
|
} |
|
return [dict create exit $code output $output] |
|
} |
|
#the verdict lines under test (parity comparisons exclude the payload-specific |
|
#guidance lines, which carry each payload's own program-name convention) |
|
proc freshlines {output} { |
|
set res {} |
|
foreach ln [split $output \n] { |
|
set ln [string trimright $ln \r] |
|
if {[string match "freshness:*" $ln]} { |
|
lappend res $ln |
|
} |
|
} |
|
return $res |
|
} |
|
|
|
#--- one-time fixture build + server launch ------------------------------------- |
|
if {[testConstraint iswindows] && [testConstraint haveruntimecmd] |
|
&& [testConstraint havebashsource] && [testConstraint havecertutil] |
|
&& [testConstraint msysbash]} { |
|
variable serverroot [makeDirectory rtfresh_server] |
|
variable stagedir [makeDirectory rtfresh_stage] |
|
file mkdir [file join $serverroot $plat] |
|
file copy -force $target [file join $stagedir punk-runtime.cmd] |
|
file copy -force $bashsource [file join $stagedir punk-runtime.bash] |
|
#server artifacts + metadata tomls + sha1sums (toml rows included - the |
|
#value-match fallback must skip support files when identifying by content) |
|
set sums {} |
|
dict for {aname acontent} $artifacts { |
|
set af [file join $serverroot $plat $aname] |
|
writefile_raw $af $acontent |
|
lappend sums "[sha1_of_file $af] *$aname" |
|
} |
|
foreach {aname rev} {fakert-alpha-r1.exe 1 fakert-alpha-r2.exe 2 fakert-beta-r1.exe 1} { |
|
set tname "[file rootname $aname].toml" |
|
set tf [file join $serverroot $plat $tname] |
|
writefile_raw $tf [artifact_toml $aname $rev] |
|
lappend sums "[sha1_of_file $tf] *$tname" |
|
} |
|
writefile_raw [file join $serverroot $plat sha1sums.txt] "[join $sums \n]\n" |
|
set_default fakert-alpha-r1.exe |
|
variable fixtureok [server_start] |
|
if {$fixtureok} { |
|
#point both payloads at the fixture server; shield the run from |
|
#ambient punk-runtime env state (restored at end of file) |
|
foreach v {PUNKBIN_URL PUNK_RUNTIME_PLATFORM PUNK_ACTIVE_RUNTIME} { |
|
if {[info exists ::env($v)]} { |
|
dict set saved_env $v $::env($v) |
|
unset ::env($v) |
|
} |
|
} |
|
set ::env(PUNKBIN_URL) $baseurl |
|
} |
|
} |
|
testConstraint fixtureserver $fixtureok |
|
variable C {iswindows haveruntimecmd havebashsource havecertutil msysbash fixtureserver} |
|
|
|
#added 2026-07-25 (agent, G-119) - fixture-server freshness verdict coverage, |
|
#both payloads with parity assertions |
|
|
|
test runtimecmd_freshness_list_ahead {active materialized from r2 with server default r1: list -remote prints an explicit AHEAD verdict naming both revisions - identically from both payloads}\ |
|
-constraints $C\ |
|
-setup { |
|
set result "" |
|
reset_stage |
|
stage_materialized fakert-alpha.exe fakert-alpha-r2.exe 2 |
|
set_default fakert-alpha-r1.exe |
|
}\ |
|
-body { |
|
set expect "freshness: active fakert-alpha.exe (r2) is AHEAD of the server default fakert-alpha-r1.exe (r1)" |
|
set rp [run_cmdroute list -remote -platform testplat-x86_64] |
|
lappend result [dict get $rp exit] |
|
lappend result [expr {[freshlines [dict get $rp output]] eq [list $expect]}] |
|
set rb [run_bashroute list -remote -platform testplat-x86_64] |
|
lappend result [dict get $rb exit] |
|
lappend result [expr {[freshlines [dict get $rb output]] eq [list $expect]}] |
|
}\ |
|
-cleanup { |
|
}\ |
|
-result [list 0 1 0 1] |
|
|
|
test runtimecmd_freshness_list_behind_guidance {active r1 with server default r2: BEHIND verdict plus fetch+use update guidance - verdict lines identical across payloads}\ |
|
-constraints $C\ |
|
-setup { |
|
set result "" |
|
reset_stage |
|
stage_materialized fakert-alpha.exe fakert-alpha-r1.exe 1 |
|
set_default fakert-alpha-r2.exe |
|
}\ |
|
-body { |
|
set expect "freshness: active fakert-alpha.exe (r1) is BEHIND the server default fakert-alpha-r2.exe (r2)" |
|
set gpat "*update: *fetch -platform testplat-x86_64*then: *use fakert-alpha-r2.exe -platform testplat-x86_64*" |
|
set rp [run_cmdroute list -remote -platform testplat-x86_64] |
|
lappend result [dict get $rp exit] |
|
lappend result [expr {[freshlines [dict get $rp output]] eq [list $expect]}] |
|
lappend result [string match $gpat [dict get $rp output]] |
|
set rb [run_bashroute list -remote -platform testplat-x86_64] |
|
lappend result [dict get $rb exit] |
|
lappend result [expr {[freshlines [dict get $rb output]] eq [list $expect]}] |
|
lappend result [string match $gpat [dict get $rb output]] |
|
}\ |
|
-cleanup { |
|
}\ |
|
-result [list 0 1 1 0 1 1] |
|
|
|
test runtimecmd_freshness_list_current_annotation {active materialized from the default's artifact: the (= server default) annotation appears and no freshness lines are printed - both payloads}\ |
|
-constraints $C\ |
|
-setup { |
|
set result "" |
|
reset_stage |
|
stage_materialized fakert-alpha.exe fakert-alpha-r1.exe 1 |
|
set_default fakert-alpha-r1.exe |
|
}\ |
|
-body { |
|
foreach r [list [run_cmdroute list -remote -platform testplat-x86_64] \ |
|
[run_bashroute list -remote -platform testplat-x86_64]] { |
|
lappend result [dict get $r exit] |
|
lappend result [string match "*active (local): fakert-alpha.exe (= server default)*" [dict get $r output]] |
|
lappend result [llength [freshlines [dict get $r output]]] |
|
} |
|
set result |
|
}\ |
|
-cleanup { |
|
}\ |
|
-result [list 0 1 0 0 1 0] |
|
|
|
test runtimecmd_freshness_prefam_no_basis {a pre-family active (no toml, no -r<N> name, sha1 matching nothing on the server) yields a stated no-revision-basis note rather than silence - both payloads}\ |
|
-constraints $C\ |
|
-setup { |
|
set result "" |
|
reset_stage |
|
stage_file oldkit.exe "LOCAL ONLY legacy kit 9999\n" |
|
set_active oldkit.exe |
|
set_default fakert-alpha-r1.exe |
|
}\ |
|
-body { |
|
set expect "freshness: active oldkit.exe has no revision basis (no -r<N> name, no metadata toml revision, sha1 matches no server artifact) - cannot compare with the server default fakert-alpha-r1.exe (r1)" |
|
foreach r [list [run_cmdroute list -remote -platform testplat-x86_64] \ |
|
[run_bashroute list -remote -platform testplat-x86_64]] { |
|
lappend result [dict get $r exit] |
|
lappend result [expr {[freshlines [dict get $r output]] eq [list $expect]}] |
|
} |
|
set result |
|
}\ |
|
-cleanup { |
|
}\ |
|
-result [list 0 1 0 1] |
|
|
|
test runtimecmd_freshness_prefam_hash_identity {a pre-family active whose sha1 VALUE-matches a server artifact is identified by content and gains that artifact's revision verdict - both payloads}\ |
|
-constraints $C\ |
|
-setup { |
|
set result "" |
|
variable artifacts |
|
reset_stage |
|
stage_file oldkit.exe [dict get $artifacts fakert-alpha-r2.exe] |
|
set_active oldkit.exe |
|
set_default fakert-alpha-r1.exe |
|
}\ |
|
-body { |
|
set expect "freshness: active oldkit.exe is server artifact fakert-alpha-r2.exe by content (r2) - AHEAD of the server default fakert-alpha-r1.exe (r1)" |
|
foreach r [list [run_cmdroute list -remote -platform testplat-x86_64] \ |
|
[run_bashroute list -remote -platform testplat-x86_64]] { |
|
lappend result [dict get $r exit] |
|
lappend result [expr {[freshlines [dict get $r output]] eq [list $expect]}] |
|
} |
|
set result |
|
}\ |
|
-cleanup { |
|
}\ |
|
-result [list 0 1 0 1] |
|
|
|
test runtimecmd_freshness_fetch_noname_note {a no-name fetch resolves the server default and prints a one-line active-vs-default note when the two diverge - both payloads (second run sees the artifact already present)}\ |
|
-constraints $C\ |
|
-setup { |
|
set result "" |
|
reset_stage |
|
stage_materialized fakert-alpha.exe fakert-alpha-r2.exe 2 |
|
set_default fakert-alpha-r1.exe |
|
}\ |
|
-body { |
|
variable stagedir |
|
variable plat |
|
set expect "freshness: active fakert-alpha.exe (r2) is AHEAD of the server default fakert-alpha-r1.exe (r1)" |
|
set rp [run_cmdroute fetch -platform testplat-x86_64] |
|
lappend result [dict get $rp exit] |
|
lappend result [expr {[freshlines [dict get $rp output]] eq [list $expect]}] |
|
#the fetch actually delivered the default artifact + its metadata toml |
|
lappend result [file exists [file join $stagedir runtime $plat fakert-alpha-r1.exe]] |
|
lappend result [file exists [file join $stagedir runtime $plat fakert-alpha-r1.toml]] |
|
#the pre-existing active selection was not stolen by the fetch |
|
set fd [open [file join $stagedir runtime $plat active.toml] r] |
|
set adata [read $fd] |
|
close $fd |
|
lappend result [string match {*active = "fakert-alpha.exe"*} $adata] |
|
set rb [run_bashroute fetch -platform testplat-x86_64] |
|
lappend result [dict get $rb exit] |
|
lappend result [expr {[freshlines [dict get $rb output]] eq [list $expect]}] |
|
}\ |
|
-cleanup { |
|
}\ |
|
-result [list 0 1 1 1 1 0 1] |
|
|
|
test runtimecmd_freshness_bash_series_mismatch_and_fetch_behind {bash payload extras: different-series actives get an incomparable verdict, and a diverging no-name fetch prints the BEHIND note with an inline activation hint}\ |
|
-constraints $C\ |
|
-setup { |
|
set result "" |
|
}\ |
|
-body { |
|
#different runtime series: revisions exist on both sides but are not comparable |
|
reset_stage |
|
stage_materialized fakert-beta.exe fakert-beta-r1.exe 1 |
|
set_default fakert-alpha-r2.exe |
|
set r [run_bashroute list -remote -platform testplat-x86_64] |
|
lappend result [dict get $r exit] |
|
lappend result [expr {[freshlines [dict get $r output]] eq [list "freshness: active fakert-beta.exe (r1) and the server default fakert-alpha-r2.exe (r2) are different runtime series - no revision comparison"]}] |
|
#fetch-mode BEHIND: one line, inline activation hint (the artifact was just fetched) |
|
reset_stage |
|
stage_materialized fakert-alpha.exe fakert-alpha-r1.exe 1 |
|
set_default fakert-alpha-r2.exe |
|
set r [run_bashroute fetch -platform testplat-x86_64] |
|
lappend result [dict get $r exit] |
|
lappend result [expr {[freshlines [dict get $r output]] eq [list "freshness: active fakert-alpha.exe (r1) is BEHIND the server default fakert-alpha-r2.exe (r2) - activate it with: use fakert-alpha-r2.exe"]}] |
|
}\ |
|
-cleanup { |
|
}\ |
|
-result [list 0 1 0 1] |
|
|
|
#added 2026-07-25 (agent, G-119) - follow-on refinement (user-directed shape): |
|
#identity middle column (from=/sha1=) so the salient starred row changes with |
|
#every 'use' switch and the Remote column carries a real server relationship |
|
|
|
test runtimecmd_freshness_identity_columns {rows the server listing does not name carry identity: from=<artifact> on a materialized working copy (starred) and sha1=<name> on a byte-copy stray, both with a real Remote status - the dead-end '(not listed on server)' no longer appears for identified rows - both payloads}\ |
|
-constraints $C\ |
|
-setup { |
|
set result "" |
|
variable artifacts |
|
reset_stage |
|
stage_materialized fakert-alpha.exe fakert-alpha-r2.exe 2 |
|
stage_file oldkit.exe [dict get $artifacts fakert-alpha-r2.exe] |
|
set_default fakert-alpha-r1.exe |
|
}\ |
|
-body { |
|
foreach r [list [run_cmdroute list -remote -platform testplat-x86_64] \ |
|
[run_bashroute list -remote -platform testplat-x86_64]] { |
|
set out [dict get $r output] |
|
lappend result [dict get $r exit] |
|
lappend result [regexp {\* fakert-alpha\.exe\s+from=fakert-alpha-r2\.exe\s+Same version} $out] |
|
lappend result [regexp {oldkit\.exe\s+sha1=fakert-alpha-r2\.exe\s+Same version} $out] |
|
lappend result [string match "*(not listed on server)*" $out] |
|
} |
|
set result |
|
}\ |
|
-cleanup { |
|
}\ |
|
-result [list 0 1 1 0 0 1 1 0] |
|
|
|
test runtimecmd_freshness_identity_default_annotation {the (server default) row annotation follows artifact identity: a working copy materialized from the default artifact carries it on the starred row - both payloads}\ |
|
-constraints $C\ |
|
-setup { |
|
set result "" |
|
reset_stage |
|
stage_materialized fakert-alpha.exe fakert-alpha-r1.exe 1 |
|
set_default fakert-alpha-r1.exe |
|
}\ |
|
-body { |
|
foreach r [list [run_cmdroute list -remote -platform testplat-x86_64] \ |
|
[run_bashroute list -remote -platform testplat-x86_64]] { |
|
lappend result [dict get $r exit] |
|
lappend result [regexp {\* fakert-alpha\.exe\s+from=fakert-alpha-r1\.exe\s+Same version\s+\(server default\)} [dict get $r output]] |
|
} |
|
set result |
|
}\ |
|
-cleanup { |
|
}\ |
|
-result [list 0 1 0 1] |
|
|
|
test runtimecmd_freshness_identity_anomaly_statuses {identified working copies surface anomalies: content differing from the immutable source artifact reports CONTENT DIFFERS, and a source artifact absent from the server listing is stated - both payloads}\ |
|
-constraints $C\ |
|
-setup { |
|
set result "" |
|
variable artifacts |
|
reset_stage |
|
#working copy claiming r1 provenance but carrying r2 bytes (modified local |
|
#copy / mismatched sidecar - artifacts are immutable, so never an "update") |
|
stage_file fakert-alpha.exe [dict get $artifacts fakert-alpha-r2.exe] |
|
stage_file fakert-alpha.toml [artifact_toml fakert-alpha-r1.exe 1] |
|
#working copy whose recorded source artifact is not on the server |
|
stage_file fakert-beta.exe [dict get $artifacts fakert-beta-r1.exe] |
|
stage_file fakert-beta.toml [artifact_toml fakert-beta-r9.exe 9] |
|
set_active fakert-alpha.exe |
|
set_default fakert-alpha-r1.exe |
|
}\ |
|
-body { |
|
foreach r [list [run_cmdroute list -remote -platform testplat-x86_64] \ |
|
[run_bashroute list -remote -platform testplat-x86_64]] { |
|
set out [dict get $r output] |
|
lappend result [dict get $r exit] |
|
lappend result [regexp {fakert-alpha\.exe\s+from=fakert-alpha-r1\.exe\s+CONTENT DIFFERS} $out] |
|
lappend result [regexp {fakert-beta\.exe\s+from=fakert-beta-r9\.exe\s+\(artifact not listed on server\)} $out] |
|
} |
|
set result |
|
}\ |
|
-cleanup { |
|
}\ |
|
-result [list 0 1 1 0 1 1] |
|
|
|
#whole-file teardown: stop the fixture server, restore shielded env state |
|
if {$fixtureok} { |
|
server_stop |
|
unset -nocomplain ::env(PUNKBIN_URL) |
|
dict for {v val} $saved_env { |
|
set ::env($v) $val |
|
} |
|
} |
|
} |
|
tcltest::cleanupTests ;#needed to produce test summary line.
|
|
|