1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
# These tests are design especially for the vfork() implementation
# of exec where sh -c must be used and thus we must take extra care
# in quoting arguments to exec.
source [file dirname [info script]]/testing.tcl
needs cmd exec
constraint cmd signal
constraint cmd wait
constraint cmd alarm
constraint cmd after
# Jim needs [pipe] to implement [open |command]
if {[testConstraint tcl]} {
testConstraint pipe 1
} else {
constraint cmd pipe
}
# Some Windows platforms (e.g. AppVeyor) produce ENOSPC rather than killing
# the child with SIGPIPE). So turn off this test for that platform
constraint expr nomingw32 {![info exists env(MSYSTEM)] || $env(MSYSTEM) ne "MINGW32"}
set d \"
set s '
set b \\
array set saveenv [array get env]
test exec2-1.1 "Quoting - Result" {
exec echo ${d}double quoted${d} ${s}single quoted${s} ${b}backslash quoted${b}
} "\"double\ quoted\"\ 'single quoted'\ \\backslash\ quoted\\"
test exec2-1.2 "Quoting - Word Grouping" {
string trim [exec echo ${d}double quoted${d} ${s}single quoted${s} ${b}backslash quoted${b} | wc -w]
} {6}
test exec2-2.1 "Add to exec environment" {
set env(TESTENV) "the value"
exec printenv | sed -n -e /^TESTENV=/p
} {TESTENV=the value}
test exec2-2.2 "Remove from exec environment" {
set env(TESTENV2) "new value"
unset env(TESTENV)
exec printenv | sed -n -e /^TESTENV=/p
} {}
test exec2-2.3 "Remove all exec environment" {
array unset env *
exec printenv | sed -n -e /^TESTENV2=/p
} {}
test exec2-2.4 "Remove all env var" {
unset -nocomplain env
exec printenv | sed -n -e /^TESTENV2=/p
} {}
array set env [array get saveenv]
test exec2-3.1 "close pipeline return value" pipe {
set f [open |false]
set rc [catch {close $f} msg opts]
lassign [dict get $opts -errorcode] status pid exitcode
list $rc $msg $status $exitcode
} {1 {child process exited abnormally} CHILDSTATUS 1}
test exec2-3.2 "close pipeline return value" -constraints {pipe signal nomingw32} -body {
signal ignore SIGPIPE
# Write more than 64KB which is maximum size of the pipe buffers
# on all systems we have seen
set bigstring [string repeat a 100000]
set f [open [list |cat << $bigstring]]
set rc [catch {close $f} msg opts]
lassign [dict get $opts -errorcode] status pid exitcode
list $rc $msg $status $exitcode
} -match glob -result {1 {child killed*} CHILDKILLED SIGPIPE}
test exec2-3.3 "close pipeline with SIGPIPE blocked" -constraints {pipe signal nomingw32} -body {
signal block SIGPIPE
# Write more than 64KB which is maximum size of the pipe buffers
# on all systems we have seen
set bigstring [string repeat a 100000]
set f [open [list |cat << $bigstring 2>/dev/null]]
set rc [catch {close $f} msg opts]
lassign [dict get $opts -errorcode] status pid exitcode
list $rc $msg $status $exitcode
} -match glob -result {1 {child process exited*} CHILDSTATUS 1} -cleanup {
signal default SIGPIPE
}
test exec2-3.4 "wait for background task" -constraints wait -body {
set pid [exec sleep 0.1 &]
lassign [wait $pid] status newpid exitcode
if {$pid != $newpid} {
error "wait $pid returned pid=$newpid"
} else {
list $status $exitcode
}
} -result {CHILDSTATUS 0}
test exec2-4.1 {redirect from invalid filehandle} -body {
exec cat <@bogus
} -returnCodes error -match glob -result {*"bogus"}
test exec2-4.2 {env is invalid dict} -constraints jim -body {
set saveenv $env
lappend env bogus
catch {exec pwd}
} -result {0} -cleanup {
set env $saveenv
}
test exec2-4.3 {signalled process during foreground exec} -constraints {jim alarm} -body {
# We need to exec a pipeline and then have one process
# be killed by a signal
exec [info nameofexecutable] -e {alarm 0.1; sleep 0.5}
} -returnCodes error -result {child killed by signal SIGALRM}
test exec2-4.4 {exec - consecutive |} -body {
exec echo | | test
} -returnCodes error -result {illegal use of | or |& in command}
test exec2-4.5 {exec - consecutive | with &} -body {
exec echo | | test &
} -returnCodes error -result {illegal use of | or |& in command}
test exec2-4.6 {exec - illegal channel} -body {
exec echo hello >@nonexistent
} -returnCodes error -match glob -result {*"nonexistent"}
test exec2-5.1 {wait with invalid pid} wait {
wait 9999999
} {NONE -1 -1}
test exec2-5.2 {wait with invalid pid} -constraints wait -body {
wait blah
} -returnCodes error -result {expected integer but got "blah"}
test exec2-5.3 {wait - bad args} -constraints wait -body {
wait too many args
} -returnCodes error -result {wrong # args: should be "wait ?-nohang? ?pid?"}
test exec2-5.4 {wait -nohang} -constraints wait -body {
set pid [exec sleep 0.2 &]
# first wait will do nothing as the process is not finished
wait -nohang $pid
wait $pid
} -match glob -result {CHILDSTATUS * 0}
test exec2-5.5 {wait for all children} -constraints {after jim} -body {
# We want to have children finish at different times
# so that we test the handling of the wait table
foreach i {0.1 0.2 0.6 0.5 0.4 0.3} {
exec sleep $i &
}
# reap zombies, there should not be any
wait
after 300
# reap zombies, 2-3 should be finished now
wait
after 400
# reap zombies, all processes should be finished now
wait
} -result {}
test exec2-5.6 {wait -1 to wait for any child} -constraints {after jim nomingw32} -body {
set pid [exec sleep 0.1 &]
# Now wait for any child
lassign [wait -1] status waitpid code
list $status $($waitpid == $pid) $code
} -result {CHILDSTATUS 1 0}
testreport
|