summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/all.tcl8
-rw-r--r--tests/async.test40
-rw-r--r--tests/chanio.test15
-rw-r--r--tests/cmdAH.test27
-rw-r--r--tests/env.test399
-rw-r--r--tests/exec.test25
-rw-r--r--tests/expr.test9
-rw-r--r--tests/fileName.test16
-rw-r--r--tests/fileSystem.test6
-rw-r--r--tests/format.test14
-rw-r--r--tests/http11.test7
-rw-r--r--tests/io.test15
-rw-r--r--tests/ioCmd.test17
-rw-r--r--tests/ioTrans.test2
-rw-r--r--tests/iogt.test2
-rw-r--r--tests/main.test2
-rw-r--r--tests/pkgIndex.tcl6
-rw-r--r--tests/platform.test6
-rw-r--r--tests/proc.test16
-rw-r--r--tests/safe.test12
-rw-r--r--tests/string.test17
-rw-r--r--tests/tailcall.test20
-rw-r--r--tests/tcltest.test15
-rw-r--r--tests/tcltests.tcl11
-rw-r--r--tests/thread.test67
-rw-r--r--tests/var.test16
-rw-r--r--tests/winFCmd.test9
-rw-r--r--tests/winPipe.test280
28 files changed, 744 insertions, 335 deletions
diff --git a/tests/all.tcl b/tests/all.tcl
index 69a16ba..e14bd9c 100644
--- a/tests/all.tcl
+++ b/tests/all.tcl
@@ -13,10 +13,14 @@
package prefer latest
package require Tcl 8.5-
package require tcltest 2.2
-namespace import tcltest::*
-configure {*}$argv -testdir [file dir [info script]]
+namespace import ::tcltest::*
+
+configure {*}$argv -testdir [file dirname [file dirname [file normalize [
+ info script]/...]]]
+
if {[singleProcess]} {
interp debug {} -frame 1
}
+
runAllTests
proc exit args {}
diff --git a/tests/async.test b/tests/async.test
index cb67cc2..e7fc45a 100644
--- a/tests/async.test
+++ b/tests/async.test
@@ -157,17 +157,24 @@ test async-4.1 {async interrupting bytecode sequence} -constraints {
}
} -body {
apply {{handle} {
- global aresult
- set aresult {Async event not delivered}
- testasync marklater $handle
- for {set i 0} {
- $i < 2500000 && $aresult eq "Async event not delivered"
- } {incr i} {
- nothing
- }
+ global aresult
+ set aresult {Async event not delivered}
+ testasync marklater $handle
+ # allow plenty of time to pass in case valgrind is running
+ set start [clock seconds]
+ while {
+ [clock seconds] - $start < 180 && $aresult eq "Async event not delivered"
+ } {
+ # be less busy
+ after 100
+ nothing
+ }
return $aresult
}} $hm
} -result {test pattern} -cleanup {
+ # give other threads some time to go way so that valgrind doesn't pick up
+ # "still reachable" cases from early thread termination
+ after 100
testasync delete $hm
}
test async-4.2 {async interrupting straight bytecode sequence} -constraints {
@@ -179,12 +186,20 @@ test async-4.2 {async interrupting straight bytecode sequence} -constraints {
global aresult
set aresult {Async event not delivered}
testasync marklater $handle
- for {set i 0} {
- $i < 2500000 && $aresult eq "Async event not delivered"
- } {incr i} {}
+ # allow plenty of time to pass in case valgrind is running
+ set start [clock seconds]
+ while {
+ [clock seconds] - $start < 180 && $aresult eq "Async event not delivered"
+ } {
+ # be less busy
+ after 100
+ }
return $aresult
}} $hm
} -result {test pattern} -cleanup {
+ # give other threads some time to go way so that valgrind doesn't pick up
+ # "still reachable" cases from early thread termination
+ after 100
testasync delete $hm
}
test async-4.3 {async interrupting loop-less bytecode sequence} -constraints {
@@ -201,6 +216,9 @@ test async-4.3 {async interrupting loop-less bytecode sequence} -constraints {
return $aresult
}]] $hm
} -result {test pattern} -cleanup {
+ # give other threads some time to go way so that valgrind doesn't pick up
+ # "still reachable" cases from early thread termination
+ after 100
testasync delete $hm
}
diff --git a/tests/chanio.test b/tests/chanio.test
index 86c1485..6408f50 100644
--- a/tests/chanio.test
+++ b/tests/chanio.test
@@ -13,16 +13,11 @@
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# TODO: This test is likely worthless. Confirm and remove
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
- namespace import -force ::tcltest::*
}
-::tcltest::loadTestedCommands
-catch [list package require -exact Tcltest [info patchlevel]]
-
-testConstraint testbytestring [llength [info commands testbytestring]]
-
namespace eval ::tcl::test::io {
namespace import ::tcltest::*
@@ -35,18 +30,16 @@ namespace eval ::tcl::test::io {
variable msg
variable expected
- ::tcltest::loadTestedCommands
+ loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
+ package require tcltests
+ testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint testchannel [llength [info commands testchannel]]
- testConstraint exec [llength [info commands exec]]
testConstraint openpipe 1
- testConstraint fileevent [llength [info commands fileevent]]
- testConstraint fcopy [llength [info commands fcopy]]
testConstraint testfevent [llength [info commands testfevent]]
testConstraint testchannelevent [llength [info commands testchannelevent]]
testConstraint testmainthread [llength [info commands testmainthread]]
- testConstraint thread [expr {0 == [catch {package require Thread 2.7-}]}]
# You need a *very* special environment to do some tests. In particular,
# many file systems do not support large-files...
diff --git a/tests/cmdAH.test b/tests/cmdAH.test
index e334dff..0377064 100644
--- a/tests/cmdAH.test
+++ b/tests/cmdAH.test
@@ -1040,7 +1040,7 @@ test cmdAH-20.7.1 {
Tcl_FileObjCmd: atime (built-in Windows names with dir path and extension)
} -constraints {win} -body {
file atime [file join [temporaryDirectory] CON.txt]
-} -result "could not get access time for file \"[file join [temporaryDirectory] CON.txt]\"" -returnCodes error
+} -match regexp -result {could not (?:get access time|read)} -returnCodes error
if {[testConstraint unix] && [file exists /tmp]} {
removeFile touch.me /tmp
@@ -1281,7 +1281,7 @@ test cmdAH-24.14.1 {
Tcl_FileObjCmd: mtime (built-in Windows names with dir path and extension)
} -constraints {win} -body {
file mtime [file join [temporaryDirectory] CON.txt]
-} -result "could not get modification time for file \"[file join [temporaryDirectory] CON.txt]\"" -returnCodes error
+} -match regexp -result {could not (?:get modification time|read)} -returnCodes error
# owned
test cmdAH-25.1 {Tcl_FileObjCmd: owned} -returnCodes error -body {
@@ -1345,7 +1345,12 @@ test cmdAH-27.4 {
test cmdAH-27.4.1 {
Tcl_FileObjCmd: size (built-in Windows names with dir path and extension)
} -constraints {win} -body {
- file size [file join [temporaryDirectory] con.txt]
+ try {
+ set res [file size [file join [temporaryDirectory] con.txt]]
+ } trap {POSIX ENOENT} {} {
+ set res 0
+ }
+ set res
} -result 0
catch {testsetplatform $platform}
@@ -1447,8 +1452,13 @@ test cmdAH-28.13 {Tcl_FileObjCmd: stat (built-in Windows names)} -constraints {w
test cmdAH-28.13.1 {Tcl_FileObjCmd: stat (built-in Windows names)} -constraints {win} -setup {
unset -nocomplain stat
} -body {
- file stat [file join [temporaryDirectory] CON.txt] stat
- lmap elem {atime ctime dev gid ino mode mtime nlink size type uid} {set stat($elem)}
+ try {
+ file stat [file join [temporaryDirectory] CON.txt] stat
+ set res [lmap elem {atime ctime dev gid ino mode mtime nlink size type uid} {set stat($elem)}]
+ } trap {POSIX ENOENT} {} {
+ set res {0 0 -1 0 0 8630 0 0 0 characterSpecial 0}
+ }
+ set res
} -result {0 0 -1 0 0 8630 0 0 0 characterSpecial 0}
unset -nocomplain stat
@@ -1498,7 +1508,12 @@ test cmdAH-29.6 {
test cmdAH-29.6.1 {
Tcl_FileObjCmd: type (built-in Windows names, with dir path and extension)
} -constraints {win} -body {
- file type [file join [temporaryDirectory] CON.txt]
+ try {
+ set res [file type [file join [temporaryDirectory] CON.txt]]
+ } trap {POSIX ENOENT} {} {
+ set res {characterSpecial}
+ }
+ set res
} -result "characterSpecial"
# Error conditions
diff --git a/tests/env.test b/tests/env.test
index 0dd4f98..e6ce44d 100644
--- a/tests/env.test
+++ b/tests/env.test
@@ -16,49 +16,96 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-# Some tests require the "exec" command.
-# Skip them if exec is not defined.
-testConstraint exec [llength [info commands exec]]
+package require tcltests
+
+# [exec] is required here to see the actual environment received by child
+# processes.
+proc getenv {} {
+ global printenvScript
+ catch {exec [interpreter] $printenvScript} out
+ if {$out eq "child process exited abnormally"} {
+ set out {}
+ }
+ return $out
+}
+
+
+proc envrestore {} {
+ # Restore the environment variables at the end of the test.
+ global env
+ variable env2
+
+ foreach name [array names env] {
+ unset env($name)
+ }
+ array set env $env2
+ return
+}
+
+
+proc envprep {} {
+ # Save the current environment variables at the start of the test.
+ global env
+ variable keep
+ variable env2
+
+ set env2 [array get env]
+ foreach name [array names env] {
+ # Keep some environment variables that support operation of the tcltest
+ # package.
+ if {[string toupper $name] ni [string toupper $keep]} {
+ unset env($name)
+ }
+ }
+ return
+}
+
+
+proc encodingrestore {} {
+ variable sysenc
+ encoding system $sysenc
+ return
+}
+
+
+proc encodingswitch encoding {
+ variable sysenc
+ # Need to run [getenv] in known encoding, so save the current one here...
+ set sysenc [encoding system]
+ encoding system $encoding
+ return
+}
+
+
+proc setup1 {} {
+ global env
+ envprep
+ encodingswitch iso8859-1
+}
+
+proc setup2 {} {
+ global env
+ setup1
+ set env(NAME1) {test string}
+ set env(NAME2) {new value}
+ set env(XYZZY) {garbage}
+}
+
+
+proc cleanup1 {} {
+ encodingrestore
+ envrestore
+}
-#
-# These tests will run on any platform (and indeed crashed on the Mac). So put
-# them before you test for the existance of exec.
-#
-test env-1.1 {propagation of env values to child interpreters} -setup {
- catch {interp delete child}
- catch {unset env(test)}
-} -body {
- interp create child
- set env(test) garbage
- child eval {set env(test)}
-} -cleanup {
- interp delete child
- unset env(test)
-} -result {garbage}
-#
-# This one crashed on Solaris under Tcl8.0, so we only want to make sure it
-# runs.
-#
-test env-1.2 {lappend to env value} -setup {
- catch {unset env(test)}
-} -body {
- set env(test) aaaaaaaaaaaaaaaa
- append env(test) bbbbbbbbbbbbbb
- unset env(test)
+variable keep {
+ TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY
+ SHLIB_PATH SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
+ DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING
+ __CF_USER_TEXT_ENCODING SECURITYSESSIONID LANG WINDIR TERM
+ CommonProgramFiles ProgramFiles CommonProgramW6432 ProgramW6432
}
-test env-1.3 {reflection of env by "array names"} -setup {
- catch {interp delete child}
- catch {unset env(test)}
-} -body {
- interp create child
- child eval {set env(test) garbage}
- expr {"test" in [array names env]}
-} -cleanup {
- interp delete child
- catch {unset env(test)}
-} -result {1}
-set printenvScript [makeFile {
+variable printenvScript [makeFile [string map [list @keep@ [list $keep]] {
encoding system iso8859-1
proc lrem {listname name} {
upvar $listname list
@@ -70,7 +117,7 @@ set printenvScript [makeFile {
}
proc mangle s {
regsub -all {\[|\\|\]} $s {\\&} s
- regsub -all "\[\u0000-\u001f\u007f-\uffff\]" $s {[manglechar &]} s
+ regsub -all "\[\u0000-\u001f\u007f-\uffff\]" $s {[manglechar {&}]} s
return [subst -novariables $s]
}
proc manglechar c {
@@ -84,161 +131,154 @@ set printenvScript [makeFile {
lrem names ComSpec
lrem names ""
}
- foreach name {
- TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY
- SHLIB_PATH SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
- DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING
- __CF_USER_TEXT_ENCODING SECURITYSESSIONID LANG WINDIR TERM
- CommonProgramFiles ProgramFiles CommonProgramW6432 ProgramW6432
- } {
+ foreach name @keep@ {
lrem names $name
}
foreach p $names {
- puts "[mangle $p]=[mangle $env($p)]"
+ puts [mangle $p]=[mangle $env($p)]
}
exit
-} printenv]
+}] printenv]
-# [exec] is required here to see the actual environment received by child
-# processes.
-proc getenv {} {
- global printenvScript tcltest
- catch {exec [interpreter] $printenvScript} out
- if {$out eq "child process exited abnormally"} {
- set out {}
- }
- return $out
-}
-# Save the current environment variables at the start of the test.
-
-set env2 [array get env]
-foreach name [array names env] {
- # Keep some environment variables that support operation of the tcltest
- # package.
- if {[string toupper $name] ni {
- TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH DISPLAY SHLIB_PATH
- SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
- DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING
- SECURITYSESSIONID LANG WINDIR TERM
- CONNOMPROGRAMFILES PROGRAMFILES COMMONPROGRAMW6432 PROGRAMW6432
- }} {
- unset env($name)
- }
+test env-1.1 {propagation of env values to child interpreters} -setup {
+ catch {interp delete child}
+ catch {unset env(test)}
+} -body {
+ interp create child
+ set env(test) garbage
+ child eval {set env(test)}
+} -cleanup {
+ interp delete child
+ unset env(test)
+} -result {garbage}
+
+
+# This one crashed on Solaris under Tcl8.0, so we only want to make sure it
+# runs.
+test env-1.2 {lappend to env value} -setup {
+ catch {unset env(test)}
+} -body {
+ set env(test) aaaaaaaaaaaaaaaa
+ append env(test) bbbbbbbbbbbbbb
+ unset env(test)
}
-# Need to run 'getenv' in known encoding, so save the current one here...
-set sysenc [encoding system]
-test env-2.1 {adding environment variables} -setup {
- encoding system iso8859-1
-} -constraints {exec} -body {
- getenv
+test env-1.3 {reflection of env by "array names"} -setup {
+ catch {interp delete child}
+ catch {unset env(test)}
+} -body {
+ interp create child
+ child eval {set env(test) garbage}
+ expr {"test" in [array names env]}
} -cleanup {
- encoding system $sysenc
-} -result {}
-test env-2.2 {adding environment variables} -setup {
- encoding system iso8859-1
-} -constraints {exec} -body {
+ interp delete child
+ catch {unset env(test)}
+} -result 1
+
+
+test env-2.1 {
+ adding environment variables
+} -constraints exec -setup setup1 -body {
+ getenv
+} -cleanup cleanup1 -result {}
+
+
+test env-2.2 {
+ adding environment variables
+} -constraints exec -setup setup1 -body {
set env(NAME1) "test string"
getenv
-} -cleanup {
- encoding system $sysenc
-} -result {NAME1=test string}
-test env-2.3 {adding environment variables} -setup {
- encoding system iso8859-1
+} -cleanup cleanup1 -result {NAME1=test string}
+
+
+test env-2.3 {adding environment variables} -constraints exec -setup {
+ setup1
set env(NAME1) "test string"
-} -constraints {exec} -body {
+} -body {
set env(NAME2) "more"
getenv
-} -cleanup {
- encoding system $sysenc
-} -result {NAME1=test string
+} -cleanup cleanup1 -result {NAME1=test string
NAME2=more}
-test env-2.4 {adding environment variables} -setup {
- encoding system iso8859-1
+
+
+test env-2.4 {
+ adding environment variables
+} -constraints exec -setup {
+ setup1
set env(NAME1) "test string"
set env(NAME2) "more"
-} -constraints {exec} -body {
+} -body {
set env(XYZZY) "garbage"
getenv
-} -cleanup {
- encoding system $sysenc
+} -cleanup { cleanup1
} -result {NAME1=test string
NAME2=more
XYZZY=garbage}
-set env(NAME1) "test string"
-set env(NAME2) "new value"
-set env(XYZZY) "garbage"
-test env-3.1 {changing environment variables} -setup {
- encoding system iso8859-1
-} -constraints {exec} -body {
+
+test env-3.1 {
+ changing environment variables
+} -constraints exec -setup setup2 -body {
set result [getenv]
unset env(NAME2)
set result
} -cleanup {
- encoding system $sysenc
+ cleanup1
} -result {NAME1=test string
NAME2=new value
XYZZY=garbage}
-unset -nocomplain env(NAME2)
-test env-4.1 {unsetting environment variables: default} -setup {
- encoding system iso8859-1
-} -constraints {exec} -body {
+
+test env-4.1 {
+ unsetting environment variables
+} -constraints exec -setup setup2 -body {
+ unset -nocomplain env(NAME2)
getenv
-} -cleanup {
- encoding system $sysenc
-} -result {NAME1=test string
+} -cleanup cleanup1 -result {NAME1=test string
XYZZY=garbage}
-test env-4.2 {unsetting environment variables} -setup {
- encoding system iso8859-1
-} -constraints {exec} -body {
- unset env(NAME1)
- getenv
-} -cleanup {
- unset env(XYZZY)
- encoding system $sysenc
-} -result {XYZZY=garbage}
-unset -nocomplain env(NAME1) env(XYZZY)
-test env-4.3 {setting international environment variables} -setup {
- encoding system iso8859-1
-} -constraints {exec} -body {
+
+# env-4.2 is deleted
+
+test env-4.3 {
+ setting international environment variables
+} -constraints exec -setup setup1 -body {
set env(\ua7) \ub6
getenv
-} -cleanup {
- encoding system $sysenc
-} -result {\u00a7=\u00b6}
-test env-4.4 {changing international environment variables} -setup {
- encoding system iso8859-1
-} -constraints {exec} -body {
+} -cleanup cleanup1 -result {\u00a7=\u00b6}
+
+
+test env-4.4 {
+ changing international environment variables
+} -constraints exec -setup setup1 -body {
set env(\ua7) \ua7
getenv
-} -cleanup {
- encoding system $sysenc
-} -result {\u00a7=\u00a7}
-test env-4.5 {unsetting international environment variables} -setup {
- encoding system iso8859-1
+} -cleanup cleanup1 -result {\u00a7=\u00a7}
+
+
+test env-4.5 {
+ unsetting international environment variables
+} -constraints exec -setup {
+ setup1
set env(\ua7) \ua7
} -body {
set env(\ub6) \ua7
unset env(\ua7)
getenv
-} -constraints {exec} -cleanup {
- unset env(\ub6)
- encoding system $sysenc
-} -result {\u00b6=\u00a7}
+} -cleanup cleanup1 -result {\u00b6=\u00a7}
-test env-5.0 {corner cases - set a value, it should exist} -body {
+test env-5.0 {
+ corner cases - set a value, it should exist
+} -setup setup1 -body {
set env(temp) a
set env(temp)
-} -cleanup {
- unset env(temp)
-} -result {a}
-test env-5.1 {corner cases - remove one elem at a time} -setup {
- set x [array get env]
-} -body {
+} -cleanup cleanup1 -result a
+
+
+test env-5.1 {
+ corner cases - remove one elem at a time
+} -setup setup1 -body {
# When no environment variables exist, the env var will contain no
# entries. The "array names" call synchs up the C-level environ array with
# the Tcl level env array. Make sure an empty Tcl array is created.
@@ -246,9 +286,9 @@ test env-5.1 {corner cases - remove one elem at a time} -setup {
unset env($e)
}
array size env
-} -cleanup {
- array set env $x
-} -result {0}
+} -cleanup cleanup1 -result 0
+
+
test env-5.2 {corner cases - unset the env array} -setup {
interp create i
} -body {
@@ -262,42 +302,54 @@ test env-5.2 {corner cases - unset the env array} -setup {
} -cleanup {
interp delete i
} -result {0}
+
+
test env-5.3 {corner cases: unset the env in master should unset child} -setup {
+ setup1
interp create i
} -body {
# Variables deleted in a master interp should be deleted in child interp
# too.
- i eval { set env(THIS_SHOULD_EXIST) a}
+ i eval {set env(THIS_SHOULD_EXIST) a}
set result [set env(THIS_SHOULD_EXIST)]
unset env(THIS_SHOULD_EXIST)
lappend result [i eval {catch {set env(THIS_SHOULD_EXIST)}}]
} -cleanup {
+ cleanup1
interp delete i
} -result {a 1}
+
+
test env-5.4 {corner cases - unset the env array} -setup {
+ setup1
interp create i
} -body {
# The info exists command should be in synch with the env array.
# Know Bug: 1737
- i eval { set env(THIS_SHOULD_EXIST) a}
+ i eval {set env(THIS_SHOULD_EXIST) a}
set result [info exists env(THIS_SHOULD_EXIST)]
lappend result [set env(THIS_SHOULD_EXIST)]
lappend result [info exists env(THIS_SHOULD_EXIST)]
} -cleanup {
+ cleanup1
interp delete i
} -result {1 a 1}
-test env-5.5 {corner cases - cannot have null entries on Windows} -constraints win -body {
+
+
+test env-5.5 {
+ corner cases - cannot have null entries on Windows
+} -constraints win -body {
set env() a
catch {set env()}
-} -result 1
+} -cleanup cleanup1 -result 1
-test env-6.1 {corner cases - add lots of env variables} -body {
+test env-6.1 {corner cases - add lots of env variables} -setup setup1 -body {
set size [array size env]
for {set i 0} {$i < 100} {incr i} {
set env(BOGUS$i) $i
}
expr {[array size env] - $size}
-} -result 100
+} -cleanup cleanup1 -result 100
test env-7.1 {[219226]: whole env array should not be unset by read} -body {
set n [array size env]
@@ -310,16 +362,20 @@ test env-7.1 {[219226]: whole env array should not be unset by read} -body {
return $n
} -result 0
-test env-7.2 {[219226]: links to env elements should not be removed by read} -body {
+test env-7.2 {
+ [219226]: links to env elements should not be removed by read
+} -setup setup1 -body {
apply {{} {
set ::env(test7_2) ok
upvar env(test7_2) elem
set ::env(PATH)
return $elem
}}
-} -result ok
+} -cleanup cleanup1 -result ok
-test env-7.3 {[9b4702]: testing existence of env(some_thing) should not destroy trace} -body {
+test env-7.3 {
+ [9b4702]: testing existence of env(some_thing) should not destroy trace
+} -setup setup1 -body {
apply {{} {
catch {unset ::env(test7_3)}
proc foo args {
@@ -330,16 +386,25 @@ test env-7.3 {[9b4702]: testing existence of env(some_thing) should not destroy
set ::env(not_yet_existent) "Now I'm here";
return [info exists ::env(test7_3)]
}}
-} -result 1
+} -cleanup cleanup1 -result 1
-# Restore the environment variables at the end of the test.
+test env-8.0 {
+ memory usage - valgrind does not report reachable memory
+} -body {
+ set res [set env(__DUMMY__) {i'm with dummy}]
+ unset env(__DUMMY__)
+ return $res
+} -result {i'm with dummy}
+
-foreach name [array names env] {
- unset env($name)
-}
-array set env $env2
# cleanup
+rename getenv {}
+rename envrestore {}
+rename envprep {}
+rename encodingrestore {}
+rename encodingswitch {}
+
removeFile $printenvScript
::tcltest::cleanupTests
return
diff --git a/tests/exec.test b/tests/exec.test
index 5542f3d..6570e57 100644
--- a/tests/exec.test
+++ b/tests/exec.test
@@ -11,9 +11,14 @@
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# There is no point in running Valgrind on cases where [exec] forks but then
+# fails and the child process doesn't go through full cleanup.
+
package require tcltest 2
namespace import -force ::tcltest::*
+package require tcltests
+
# All tests require the "exec" command.
# Skip them if exec is not defined.
testConstraint exec [llength [info commands exec]]
@@ -325,11 +330,11 @@ test exec-8.2 {long input and output} {exec} {
# Commands that return errors.
-test exec-9.1 {commands returning errors} {exec} {
+test exec-9.1 {commands returning errors} {exec notValgrind} {
set x [catch {exec gorp456} msg]
list $x [string tolower $msg] [string tolower $errorCode]
} {1 {couldn't execute "gorp456": no such file or directory} {posix enoent {no such file or directory}}}
-test exec-9.2 {commands returning errors} {exec} {
+test exec-9.2 {commands returning errors} {exec notValgrind} {
string tolower [list [catch {exec [interpreter] echo foo | foo123} msg] $msg $errorCode]
} {1 {couldn't execute "foo123": no such file or directory} {posix enoent {no such file or directory}}}
test exec-9.3 {commands returning errors} -constraints {exec stdio} -body {
@@ -339,7 +344,7 @@ test exec-9.4 {commands returning errors} -constraints {exec stdio} -body {
exec [interpreter] $path(exit) 43 | [interpreter] $path(echo) "foo bar"
} -returnCodes error -result {foo bar
child process exited abnormally}
-test exec-9.5 {commands returning errors} -constraints {exec stdio} -body {
+test exec-9.5 {commands returning errors} -constraints {exec stdio notValgrind} -body {
exec gorp456 | [interpreter] echo a b c
} -returnCodes error -result {couldn't execute "gorp456": no such file or directory}
test exec-9.6 {commands returning errors} -constraints {exec} -body {
@@ -428,13 +433,13 @@ test exec-10.19 {errors in exec invocation} -constraints {exec} -body {
exec cat >@ $f
} -returnCodes error -result "channel \"$f\" wasn't opened for writing"
close $f
-test exec-10.20 {errors in exec invocation} -constraints {exec} -body {
+test exec-10.20 {errors in exec invocation} -constraints {exec notValgrind} -body {
exec ~non_existent_user/foo/bar
} -returnCodes error -result {user "non_existent_user" doesn't exist}
-test exec-10.21 {errors in exec invocation} -constraints {exec} -body {
+test exec-10.21 {errors in exec invocation} -constraints {exec notValgrind} -body {
exec [interpreter] true | ~xyzzy_bad_user/x | false
} -returnCodes error -result {user "xyzzy_bad_user" doesn't exist}
-test exec-10.22 {errors in exec invocation} -constraints exec -body {
+test exec-10.22 {errors in exec invocation} -constraints {exec notValgrind} -body {
exec echo test > ~non_existent_user/foo/bar
} -returnCodes error -result {user "non_existent_user" doesn't exist}
# Commands in background.
@@ -510,7 +515,7 @@ test exec-13.1 {setting errorCode variable} {exec} {
test exec-13.2 {setting errorCode variable} {exec} {
list [catch {exec [interpreter] $path(cat) > a/b/c} msg] [string tolower $errorCode]
} {1 {posix enoent {no such file or directory}}}
-test exec-13.3 {setting errorCode variable} {exec} {
+test exec-13.3 {setting errorCode variable} {exec notValgrind} {
set x [catch {exec _weird_cmd_} msg]
list $x [string tolower $msg] [lindex $errorCode 0] \
[string tolower [lrange $errorCode 2 end]]
@@ -548,7 +553,7 @@ test exec-14.2 {-keepnewline switch} -constraints {exec} -body {
test exec-14.3 {unknown switch} -constraints {exec} -body {
exec -gorp
} -returnCodes error -result {bad option "-gorp": must be -ignorestderr, -keepnewline, or --}
-test exec-14.4 {-- switch} -constraints {exec} -body {
+test exec-14.4 {-- switch} -constraints {exec notValgrind} -body {
exec -- -gorp
} -returnCodes error -result {couldn't execute "-gorp": no such file or directory}
test exec-14.5 {-ignorestderr switch} {exec} {
@@ -662,7 +667,7 @@ test exec-18.2 {exec cat deals with weird file names} -body {
# Note that this test cannot be adapted to work on Windows; that platform has
# no kernel support for an analog of O_APPEND. OTOH, that means we can assume
# that there is a POSIX shell...
-test exec-19.1 {exec >> uses O_APPEND} -constraints {exec unix} -setup {
+test exec-19.1 {exec >> uses O_APPEND} -constraints {exec unix notValgrind} -setup {
set tmpfile [makeFile {0} tmpfile.exec-19.1]
} -body {
# Note that we have to allow for the current contents of the temporary
@@ -675,7 +680,7 @@ test exec-19.1 {exec >> uses O_APPEND} -constraints {exec unix} -setup {
{for a in a b c; do sleep 1; echo $a; done} >>$tmpfile &
exec /bin/sh -c \
{for a in d e f; do sleep 1; echo $a >&2; done} 2>>$tmpfile &
- # The above four shell invokations take about 3 seconds to finish, so allow
+ # The above four shell invocations take about 3 seconds to finish, so allow
# 5s (in case the machine is busy)
after 5000
# Check that no bytes have got lost through mixups with overlapping
diff --git a/tests/expr.test b/tests/expr.test
index fd11870..a265ac6 100644
--- a/tests/expr.test
+++ b/tests/expr.test
@@ -7196,6 +7196,15 @@ test expr-51.1 {test round-to-even on input} {
expr 6.9294956446009195e15
} 6929495644600920.0
+test expr-52.1 {
+ comparison with empty string does not generate string representation
+} {
+ set a [list one two three]
+ list [expr {$a eq {}}] [expr {$a < {}}] [expr {$a > {}}] [
+ string match {*no string representation*} [
+ ::tcl::unsupported::representation $a]]
+} {0 0 1 1}
+
# cleanup
diff --git a/tests/fileName.test b/tests/fileName.test
index ce89623..7f983a7 100644
--- a/tests/fileName.test
+++ b/tests/fileName.test
@@ -778,6 +778,8 @@ test filename-11.16 {Tcl_GlobCmd} {
} {globTest}
set globname "globTest"
set horribleglobname "glob\[\{Test"
+set tildeglobname "./~test.txt"
+
test filename-11.17 {Tcl_GlobCmd} {unix} {
lsort [glob -directory $globname *]
} [lsort [list [file join $globname a1] [file join $globname a2]\
@@ -917,11 +919,12 @@ test filename-11.21.1 {Tcl_GlobCmd} -body {
} -result {{[tcl].testremains}}
# Get rid of file/dir if it exists, since it will have been left behind by a
# previous failed run.
-if {[file exists $horribleglobname]} {
- file delete -force $horribleglobname
-}
+file delete -force $horribleglobname
file rename globTest $horribleglobname
set globname $horribleglobname
+file delete -force $tildeglobname
+close [open $tildeglobname w]
+
test filename-11.22 {Tcl_GlobCmd} {unix} {
lsort [glob -dir $globname *]
} [lsort [list [file join $globname a1] [file join $globname a2]\
@@ -1040,7 +1043,9 @@ test filename-11.41 {Tcl_GlobCmd} -body {
test filename-11.42 {Tcl_GlobCmd} -body {
set res [list]
foreach f [glob -dir [pwd] *] {
- lappend res [file tail $f]
+ set f [file tail $f]
+ regsub {^./} $f {} f; # until glob bug [2511011fff] don't fixed (tilde expansion prevention).
+ lappend res $f
}
list $res [glob *]
} -match compareWords -result equal
@@ -1080,8 +1085,9 @@ test filename-11.49 {Tcl_GlobCmd} -returnCodes error -body {
} -result {bad argument to "-types": abcde}
file rename $horribleglobname globTest
+file delete -force $tildeglobname
set globname globTest
-unset horribleglobname
+unset horribleglobname tildeglobname
test filename-12.1 {simple globbing} {unixOrPc} {
glob {}
diff --git a/tests/fileSystem.test b/tests/fileSystem.test
index b805780..f778112 100644
--- a/tests/fileSystem.test
+++ b/tests/fileSystem.test
@@ -264,6 +264,12 @@ removeDirectory dir.dir
test filesystem-1.30 {normalisation of nonexistent user} -body {
file normalize ~noonewiththisname
} -returnCodes error -result {user "noonewiththisname" doesn't exist}
+test filesystem-1.30.1 {normalisation of existing user} -body {
+ catch {file normalize ~$::tcl_platform(user)}
+} -result {0}
+test filesystem-1.30.2 {normalisation of nonexistent user specified as user@domain} -body {
+ file normalize ~nonexistentuser@nonexistentdomain
+} -returnCodes error -result {user "nonexistentuser@nonexistentdomain" doesn't exist}
test filesystem-1.31 {link normalisation: link near filesystem root} {testsetplatform} {
testsetplatform unix
file normalize /foo/../bar
diff --git a/tests/format.test b/tests/format.test
index 2795ac2..88013cf 100644
--- a/tests/format.test
+++ b/tests/format.test
@@ -585,6 +585,20 @@ test format-19.3 {Bug 2830354} {
string length [format %340f 0]
} 340
+test format-19.4.1 {Bug d498578df4: width overflow should cause limit exceeded} \
+-constraints {longIs32bit} -body {
+ # in case of overflow into negative, it produces width -2 (and limit exceeded),
+ # in case of width will be unsigned, it will be outside limit (2GB for 32bit)...
+ # and it don't throw an error in case the bug is not fixed (and probably no segfault).
+ format %[expr {0xffffffff - 1}]g 0
+} -returnCodes error -result "max size for a Tcl value exceeded"
+
+test format-19.4.2 {Bug d498578df4: width overflow should cause limit exceeded} -body {
+ # limit should exceeds in any case,
+ # and it don't throw an error in case the bug is not fixed (and probably no segfault).
+ format %[expr {0xffffffffffffffff - 1}]g 0
+} -returnCodes error -result "max size for a Tcl value exceeded"
+
# Note that this test may fail in future versions
test format-20.1 {Bug 2932421: plain %s caused intrep change of args} -body {
set x [dict create a b c d]
diff --git a/tests/http11.test b/tests/http11.test
index 8483aa3..1e30802 100644
--- a/tests/http11.test
+++ b/tests/http11.test
@@ -663,6 +663,13 @@ test http11-4.3 "normal post request, check channel query length" -setup {
# -------------------------------------------------------------------------
+# Eliminate valgrind "still reachable" reports on outstanding "Detached"
+# structures in the detached list which stem from PipeClose2Proc not waiting
+# around for background processes to complete, meaning that previous calls to
+# Tcl_ReapDetachedProcs might not have had a chance to reap all processes.
+after 10
+exec [info nameofexecutable] << {}
+
foreach p {create_httpd httpd_read halt_httpd meta check_crc} {
if {[llength [info proc $p]]} {rename $p {}}
}
diff --git a/tests/io.test b/tests/io.test
index cdecb7b..996e125 100644
--- a/tests/io.test
+++ b/tests/io.test
@@ -15,14 +15,8 @@
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
- namespace import -force ::tcltest::*
}
-::tcltest::loadTestedCommands
-catch [list package require -exact Tcltest [info patchlevel]]
-
-testConstraint testbytestring [llength [info commands testbytestring]]
-
namespace eval ::tcl::test::io {
namespace import ::tcltest::*
@@ -35,15 +29,16 @@ namespace eval ::tcl::test::io {
variable msg
variable expected
+ loadTestedCommands
+ catch [list package require -exact Tcltest [info patchlevel]]
+ package require tcltests
+
+testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint testchannel [llength [info commands testchannel]]
-testConstraint exec [llength [info commands exec]]
testConstraint openpipe 1
-testConstraint fileevent [llength [info commands fileevent]]
-testConstraint fcopy [llength [info commands fcopy]]
testConstraint testfevent [llength [info commands testfevent]]
testConstraint testchannelevent [llength [info commands testchannelevent]]
testConstraint testmainthread [llength [info commands testmainthread]]
-testConstraint thread [expr {0 == [catch {package require Thread 2.7-}]}]
testConstraint testobj [llength [info commands testobj]]
# You need a *very* special environment to do some tests. In
diff --git a/tests/ioCmd.test b/tests/ioCmd.test
index cab4e97..948671e 100644
--- a/tests/ioCmd.test
+++ b/tests/ioCmd.test
@@ -21,10 +21,10 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
+package require tcltests
+
# Custom constraints used in this file
-testConstraint fcopy [llength [info commands fcopy]]
testConstraint testchannel [llength [info commands testchannel]]
-testConstraint thread [expr {0 == [catch {package require Thread 2.7-}]}]
#----------------------------------------------------------------------
@@ -395,7 +395,7 @@ test iocmd-11.2 {I/O to command pipelines} {unixOrPc unixExecs} {
test iocmd-11.3 {I/O to command pipelines} {unixOrPc unixExecs} {
list [catch {open "| echo > \"$path(test5)\"" r+} msg] $msg $::errorCode
} {1 {can't read output from command: standard output was redirected} {TCL OPERATION EXEC BADREDIRECT}}
-test iocmd-11.4 {I/O to command pipelines} unixOrPc {
+test iocmd-11.4 {I/O to command pipelines} {notValgrind unixOrPc} {
list [catch {open "| no_such_command_exists" rb} msg] $msg $::errorCode
} {1 {couldn't execute "no_such_command_exists": no such file or directory} {POSIX ENOENT {no such file or directory}}}
@@ -3781,7 +3781,6 @@ test iocmd.tf-32.0 {origin thread of moved channel gone} -match glob -body {
# Use constraints to skip this test while valgrinding so this expected leak
# doesn't prevent a finding of "leak-free".
#
-testConstraint notValgrind [expr {![testConstraint valgrind]}]
test iocmd.tf-32.1 {origin thread of moved channel destroyed during access} -match glob -body {
#puts <<$tcltest::mainThread>>main
@@ -3834,6 +3833,16 @@ test iocmd.tf-32.1 {origin thread of moved channel destroyed during access} -mat
rename track {}
# cleanup
+
+
+# Eliminate valgrind "still reachable" reports on outstanding "Detached"
+# structures in the detached list which stem from PipeClose2Proc not waiting
+# around for background processes to complete, meaning that previous calls to
+# Tcl_ReapDetachedProcs might not have had a chance to reap all processes.
+after 10
+exec [info nameofexecutable] << {}
+
+
foreach file [list test1 test2 test3 test4] {
removeFile $file
}
diff --git a/tests/ioTrans.test b/tests/ioTrans.test
index 3bebc70..85e427a 100644
--- a/tests/ioTrans.test
+++ b/tests/ioTrans.test
@@ -1240,8 +1240,8 @@ test iortrans-11.1 {origin interpreter of moved transform destroyed during acces
set res
}]
} -cleanup {
- tempdone
interp delete $idb
+ tempdone
} -result {Owner lost}
test iortrans-11.2 {delete interp of reflected transform} -setup {
interp create slave
diff --git a/tests/iogt.test b/tests/iogt.test
index 1ed89f7..269a0ba 100644
--- a/tests/iogt.test
+++ b/tests/iogt.test
@@ -608,7 +608,7 @@ test iogt-3.0 {Tcl_Channel valid after stack/unstack, fevent handling} -setup {
variable copy 1
}
} -constraints {testchannel knownBug} -body {
- # This test to check the validity of aquired Tcl_Channel references is not
+ # This test to check the validity of acquired Tcl_Channel references is not
# possible because even a backgrounded fcopy will immediately start to
# copy data, without waiting for the event loop. This is done only in case
# of an underflow on the read size!. So stacking transforms after the
diff --git a/tests/main.test b/tests/main.test
index 351fd4f..b0edb84 100644
--- a/tests/main.test
+++ b/tests/main.test
@@ -1210,8 +1210,6 @@ namespace eval ::tcl::test::main {
Bug 1775878
} -constraints {
exec Tcltest
- } -setup {
- catch {set f [open "|[list [interpreter]]" w+]}
} -body {
exec [interpreter] << "testsetmainloop\nputs \\\npwd\ntestexitmainloop" >& result
set f [open result]
diff --git a/tests/pkgIndex.tcl b/tests/pkgIndex.tcl
new file mode 100644
index 0000000..854b943
--- /dev/null
+++ b/tests/pkgIndex.tcl
@@ -0,0 +1,6 @@
+#! /usr/bin/env tclsh
+
+package ifneeded tcltests 0.1 "
+ source [list $dir/tcltests.tcl]
+ package provide tcltests 0.1
+"
diff --git a/tests/platform.test b/tests/platform.test
index 8ee0ec7..e5a4c90 100644
--- a/tests/platform.test
+++ b/tests/platform.test
@@ -10,6 +10,7 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
package require tcltest 2
+package require tcltests
namespace eval ::tcl::test::platform {
namespace import ::tcltest::testConstraint
@@ -67,7 +68,10 @@ test platform-3.1 {CPU ID on Windows/UNIX} \
# format of string it produces consists of two non-empty words separated by a
# hyphen.
package require platform
-test platform-4.1 {format of platform::identify result} -match regexp -body {
+test platform-4.1 {format of platform::identify result} -constraints notValgrind -match regexp -body {
+ # [identify] may attempt to [exec] dpkg-architecture, which may not exist,
+ # in which case fork will not be followed by exec, and valgrind will issue
+ # "still reachable" reports.
platform::identify
} -result {^([^-]+-)+[^-]+$}
test platform-4.2 {format of platform::generic result} -match regexp -body {
diff --git a/tests/proc.test b/tests/proc.test
index e06720e..8b25b0a 100644
--- a/tests/proc.test
+++ b/tests/proc.test
@@ -110,6 +110,14 @@ test proc-1.8 {Tcl_ProcObjCmd, check that formal parameter names are simple name
proc p {b:a b::a} {
}
} -returnCodes error -result {formal parameter "b::a" is not a simple name}
+test proc-1.9 {Tcl_ProcObjCmd, arguments via canonical list (string-representation bug [631b4c45df])} -body {
+ set v 2
+ binary scan AB cc a b
+ proc p [list [list a $a] [list b $b] [list v [expr {$v + 2}]]] {expr {$a + $b + $v}}
+ p
+} -result [expr {65+66+4}] -cleanup {
+ rename p {}
+}
test proc-2.1 {TclFindProc, simple proc name and proc not in namespace} -setup {
catch {namespace delete {*}[namespace children :: test_ns_*]}
@@ -383,6 +391,14 @@ test proc-7.4 {Proc struct outlives its interp: Bug 3532959} {
interp delete slave
unset lambda
} {}
+
+test proc-7.5 {[631b4c45df] Crash in argument processing} {
+ binary scan A c val
+ proc foo [list [list from $val]] {}
+ rename foo {}
+ unset -nocomplain val
+} {}
+
# cleanup
catch {rename p ""}
diff --git a/tests/safe.test b/tests/safe.test
index 5ffdcc5..11ad2a9 100644
--- a/tests/safe.test
+++ b/tests/safe.test
@@ -308,14 +308,10 @@ test safe-8.7 {safe source control on file} -setup {
unset log
safe::interpDelete $i
} -result [list 1 {no such file or directory} [list "ERROR for slave a : [file join [info library] xxxxxxxxxxx.tcl]:no such file or directory"]]
-test safe-8.8 {safe source forbids -rsrc} -setup {
- catch {safe::interpDelete $i}
- safe::interpCreate $i
-} -body {
- $i eval {source -rsrc Init}
-} -returnCodes error -cleanup {
- safe::interpDelete $i
-} -result {wrong # args: should be "source ?-encoding E? fileName"}
+test safe-8.8 {safe source forbids -rsrc} emptyTest {
+ # Disabled this test. It was only useful for long unsupported
+ # Mac OS 9 systems. [Bug 860a9f1945]
+} {}
test safe-8.9 {safe source and return} -setup {
set returnScript [makeFile {return "ok"} return.tcl]
catch {safe::interpDelete $i}
diff --git a/tests/string.test b/tests/string.test
index d69fda4..8fc5b0e 100644
--- a/tests/string.test
+++ b/tests/string.test
@@ -24,7 +24,7 @@ catch [list package require -exact Tcltest [info patchlevel]]
testConstraint testobj [expr {[info commands testobj] != {}}]
testConstraint testindexobj [expr {[info commands testindexobj] != {}}]
-testConstraint fullutf [expr {[format %c 0x010000] != "\ufffd"}]
+testConstraint tip389 [expr {[string length \U010000] == 2}]
# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]
@@ -291,6 +291,9 @@ test string-5.19 {string index, bytearray object out of bounds} {
test string-5.20 {string index, bytearray object out of bounds} {
string index [binary format I* {0x50515253 0x52}] 20
} {}
+test string-5.21 {string index, surrogates, bug [11ae2be95dac9417]} tip389 {
+ list [string index a\U100000b 1] [string index a\U100000b 2] [string index a\U100000b 3]
+} [list \U100000 {} b]
proc largest_int {} {
@@ -1280,7 +1283,7 @@ test string-12.22 {string range, shimmering binary/index} {
binary scan $s a* x
string range $s $s end
} 000000001
-test string-12.23 {string range, surrogates, bug [11ae2be95dac9417]} fullutf {
+test string-12.23 {string range, surrogates, bug [11ae2be95dac9417]} tip389 {
list [string range a\U100000b 1 1] [string range a\U100000b 2 2] [string range a\U100000b 3 3]
} [list \U100000 {} b]
@@ -1477,6 +1480,10 @@ test string-17.7 {string totitle, unicode} {
test string-17.8 {string totitle, compiled} {
lindex [string totitle [list aa bb [list cc]]] 0
} Aa
+test string-17.9 {string totitle, surrogates, bug [11ae2be95dac9417]} tip389 {
+ list [string totitle a\U118c0c 1 1] [string totitle a\U118c0c 2 2] \
+ [string totitle a\U118c0c 3 3]
+} [list a\U118a0c a\U118c0C a\U118c0C]
test string-18.1 {string trim} {
list [catch {string trim} msg] $msg
@@ -2008,6 +2015,12 @@ test string-29.4 {string cat, many args} {
list $r1 $r2
} {0 0}
+test string-30.1.1 {[Bug ba921a8d98]: string cat} {
+ string cat [set data [binary format a* hello]] [encoding convertto $data] [unset data]
+} hellohello
+test string-30.1.2 {[Bug ba921a8d98]: inplace cat by subst (compiled to "strcat" instruction)} {
+ set x "[set data [binary format a* hello]][encoding convertto $data][unset data]"
+} hellohello
# cleanup
diff --git a/tests/tailcall.test b/tests/tailcall.test
index 26f3cbf..3751c35 100644
--- a/tests/tailcall.test
+++ b/tests/tailcall.test
@@ -688,6 +688,26 @@ if {[testConstraint testnrelevels]} {
namespace delete testnre
}
+test tailcall-14.1 {in a deleted namespace} -body {
+ namespace eval ns {
+ proc p args {
+ tailcall [namespace current] $args
+ }
+ namespace delete [namespace current]
+ p
+ }
+} -returnCodes 1 -result {namespace "::ns" not found}
+
+test tailcall-14.1-bc {{in a deleted namespace} {byte compiled}} -body {
+ namespace eval ns {
+ proc p args {
+ tailcall [namespace current] {*}$args
+ }
+ namespace delete [namespace current]
+ p
+ }
+} -returnCodes 1 -result {namespace "::ns" not found}
+
# cleanup
::tcltest::cleanupTests
diff --git a/tests/tcltest.test b/tests/tcltest.test
index 728a018..e176b0c 100644
--- a/tests/tcltest.test
+++ b/tests/tcltest.test
@@ -312,7 +312,7 @@ test tcltest-5.5 {InitConstraints: list of built-in constraints} \
-result [lsort {
95 98 asyncPipeClose eformat emptyTest exec hasIsoLocale interactive
knownBug mac macCrash macOnly macOrPc macOrUnix macOrWin nonBlockFiles
- nonPortable notRoot nt pc pcCrash pcOnly root singleTestInterp socket
+ nonPortable notRoot nt pc pcCrash pcOnly root singleTestInterp slowTest socket
stdio tempNotMac tempNotPc tempNotUnix tempNotWin unix unixCrash unixExecs
unixOnly unixOrPc unixOrWin userInteraction win winCrash winOnly
}]
@@ -550,6 +550,7 @@ switch -- $::tcl_platform(platform) {
file attributes $notWriteableDir -permissions 00555
}
default {
+ # note in FAT/NTFS we won't be able to protect directory with read-only attribute...
catch {file attributes $notWriteableDir -readonly 1}
catch {testchmod 0 $notWriteableDir}
}
@@ -566,9 +567,10 @@ test tcltest-8.3 {tcltest a.tcl -tmpdir notReadableDir} {
# This constraint doesn't go at the top of the file so that it doesn't
# interfere with tcltest-5.5
testConstraint notFAT [expr {
- ![string match "FAT*" [lindex [file system $notWriteableDir] 1]]
+ ![regexp {^(FAT\d*|NTFS)$} [lindex [file system $notWriteableDir] 1]]
+ || $::tcl_platform(platform) eq "unix" || [llength [info commands testchmod]]
}]
-# FAT permissions are fairly hopeless; ignore this test if that FS is used
+# FAT/NTFS permissions are fairly hopeless; ignore this test if that FS is used
test tcltest-8.4 {tcltest a.tcl -tmpdir notWriteableDir} {
-constraints {unixOrPc notRoot notFAT}
-body {
@@ -906,7 +908,9 @@ removeFile load.tcl
# [interpreter]
test tcltest-13.1 {interpreter} {
+ -constraints notValgrind
-setup {
+ #to do: Why is $::tcltest::tcltest being saved and restored here?
set old $::tcltest::tcltest
set ::tcltest::tcltest tcltest
}
@@ -918,6 +922,11 @@ test tcltest-13.1 {interpreter} {
}
-result {tcltest tclsh tclsh}
-cleanup {
+ # writing ::tcltest::tcltest triggers a trace that sets up the stdio
+ # constraint, which involves a call to [exec] that might fail after
+ # "fork" and before "exec", in which case the forked process will not
+ # have a chance to clean itself up before exiting, which causes
+ # valgrind to issue numerous "still reachable" reports.
set ::tcltest::tcltest $old
}
}
diff --git a/tests/tcltests.tcl b/tests/tcltests.tcl
new file mode 100644
index 0000000..74d1b40
--- /dev/null
+++ b/tests/tcltests.tcl
@@ -0,0 +1,11 @@
+#! /usr/bin/env tclsh
+
+package require tcltest 2.2
+namespace import ::tcltest::*
+
+testConstraint exec [llength [info commands exec]]
+testConstraint fcopy [llength [info commands fcopy]]
+testConstraint fileevent [llength [info commands fileevent]]
+testConstraint thread [
+ expr {0 == [catch {package require Thread 2.7-}]}]
+testConstraint notValgrind [expr {![testConstraint valgrind]}]
diff --git a/tests/thread.test b/tests/thread.test
index cc4c871..eaaaa41 100644
--- a/tests/thread.test
+++ b/tests/thread.test
@@ -11,25 +11,19 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest 2.2
- namespace import -force ::tcltest::*
-}
+
+# when thread::release is used, -wait is passed in order allow the thread to
+# be fully finalized, which avoids valgrind "still reachable" reports.
+
+package require tcltests
::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
# Some tests require the testthread command
-testConstraint testthread [expr {[info commands testthread] != {}}]
-
-# Some tests require the Thread package
-
-testConstraint thread [expr {0 == [catch {package require Thread 2.7-}]}]
+testConstraint testthread [expr {[info commands testthread] ne {}}]
-# Some tests may not work under valgrind
-
-testConstraint notValgrind [expr {![testConstraint valgrind]}]
set threadSuperKillScript {
rename catch ""
@@ -72,6 +66,17 @@ proc ThreadError {id info} {
set threadSawError($id) true; # signal main thread to exit [vwait].
}
+proc threadSuperKill id {
+ variable threadSuperKillScript
+ try {
+ thread::send $id $::threadSuperKillScript
+ } on error {tres topts} {
+ if {$tres ne {target thread died}} {
+ return -options $topts $tres
+ }
+ }
+}
+
if {[testConstraint thread]} {
thread::errorproc ThreadError
}
@@ -96,22 +101,22 @@ test thread-1.3 {Tcl_ThreadObjCmd: initial thread list} {thread} {
test thread-1.4 {Tcl_ThreadObjCmd: thread create } {thread} {
set serverthread [thread::create -preserved]
set numthreads [llength [thread::names]]
- thread::release $serverthread
+ thread::release -wait $serverthread
set numthreads
-} {2}
+} 2
test thread-1.5 {Tcl_ThreadObjCmd: thread create one shot} {thread} {
thread::create {set x 5}
foreach try {0 1 2 4 5 6} {
- # Try various ways to yield
- update
- after 10
- set l [llength [thread::names]]
- if {$l == 1} {
- break
- }
+ # Try various ways to yield
+ update
+ after 10
+ set l [llength [thread::names]]
+ if {$l == 1} {
+ break
+ }
}
set l
-} {1}
+} 1
test thread-1.6 {Tcl_ThreadObjCmd: thread exit} {thread} {
thread::create {{*}{}}
update
@@ -121,13 +126,13 @@ test thread-1.6 {Tcl_ThreadObjCmd: thread exit} {thread} {
test thread-1.13 {Tcl_ThreadObjCmd: send args} {thread} {
set serverthread [thread::create -preserved]
set five [thread::send $serverthread {set x 5}]
- thread::release $serverthread
+ thread::release -wait $serverthread
set five
} 5
test thread-1.15 {Tcl_ThreadObjCmd: wait} {thread} {
set serverthread [thread::create -preserved {set z 5 ; thread::wait}]
set five [thread::send $serverthread {set z}]
- thread::release $serverthread
+ thread::release -wait $serverthread
set five
} 5
@@ -159,7 +164,7 @@ test thread-3.1 {TclThreadList} {thread} {
set l2 [thread::names]
set c [string compare [lsort [concat [thread::id] $l1]] [lsort $l2]]
foreach t $l1 {
- thread::release $t
+ thread::release -wait $t
}
list $len $c
} {1 0}
@@ -887,7 +892,7 @@ test thread-7.24 {cancel: nested catch inside pure bytecode loop} {thread drainE
# wait for other thread to signal "ready to cancel"
vwait ::threadIdStarted; after 1000
set res [thread::cancel $serverthread]
- thread::send $serverthread $::threadSuperKillScript
+ threadSuperKill $serverthread
vwait ::threadSawError($serverthread)
thread::join $serverthread; drainEventQueue
list $res [expr {[info exists ::threadIdStarted] ? \
@@ -929,7 +934,7 @@ test thread-7.25 {cancel: nested catch inside pure inside-command loop} {thread
# wait for other thread to signal "ready to cancel"
vwait ::threadIdStarted; after 1000
set res [thread::cancel $serverthread]
- thread::send $serverthread $::threadSuperKillScript
+ threadSuperKill $serverthread
vwait ::threadSawError($serverthread)
thread::join $serverthread; drainEventQueue
list $res [expr {[info exists ::threadIdStarted] ? \
@@ -1029,7 +1034,7 @@ test thread-7.28 {cancel: send async cancel nested catch inside pure bytecode lo
# wait for other thread to signal "ready to cancel"
vwait ::threadIdStarted; after 1000
set res [thread::send -async $serverthread {interp cancel}]
- thread::send $serverthread $::threadSuperKillScript
+ threadSuperKill $serverthread
vwait ::threadSawError($serverthread)
thread::join $serverthread; drainEventQueue
list $res [expr {[info exists ::threadIdStarted] ? \
@@ -1071,7 +1076,7 @@ test thread-7.29 {cancel: send async cancel nested catch pure inside-command loo
# wait for other thread to signal "ready to cancel"
vwait ::threadIdStarted; after 1000
set res [thread::send -async $serverthread {interp cancel}]
- thread::send $serverthread $::threadSuperKillScript
+ threadSuperKill $serverthread
vwait ::threadSawError($serverthread)
thread::join $serverthread; drainEventQueue
list $res [expr {[info exists ::threadIdStarted] ? \
@@ -1111,7 +1116,7 @@ test thread-7.30 {cancel: send async thread cancel nested catch inside pure byte
# wait for other thread to signal "ready to cancel"
vwait ::threadIdStarted; after 1000
set res [thread::send -async $serverthread {thread::cancel [thread::id]}]
- thread::send $serverthread $::threadSuperKillScript
+ threadSuperKill $serverthread
vwait ::threadSawError($serverthread)
thread::join $serverthread; drainEventQueue
list $res [expr {[info exists ::threadIdStarted] ? \
@@ -1153,7 +1158,7 @@ test thread-7.31 {cancel: send async thread cancel nested catch pure inside-comm
# wait for other thread to signal "ready to cancel"
vwait ::threadIdStarted; after 1000
set res [thread::send -async $serverthread {thread::cancel [thread::id]}]
- thread::send $serverthread $::threadSuperKillScript
+ threadSuperKill $serverthread
vwait ::threadSawError($serverthread)
thread::join $serverthread; drainEventQueue
list $res [expr {[info exists ::threadIdStarted] ? \
diff --git a/tests/var.test b/tests/var.test
index b235e5d..8d86fce 100644
--- a/tests/var.test
+++ b/tests/var.test
@@ -776,6 +776,22 @@ test var-13.1 {Tcl_UnsetVar2, unset array with trace set on element} -setup {
}
set x "If you see this, it worked"
} -result "If you see this, it worked"
+test var-13.2 {unset array with search, bug 46a2410650} -body {
+ apply {{} {
+ array set a {aa 11 bb 22 cc 33 dd 44 ee 55 ff 66}
+ set s [array startsearch a]
+ unset a([array nextelement a $s])
+ array nextelement a $s
+ }}
+} -returnCodes error -result {couldn't find search "s-1-a"}
+test var-13.3 {unset array with search, SIGSEGV, bug 46a2410650} -body {
+ apply {{} {
+ array set a {aa 11 bb 22 cc 33 dd 44 ee 55 ff 66}
+ set s [array startsearch a]
+ unset a(ff)
+ array nextelement a $s
+ }}
+} -returnCodes error -result {couldn't find search "s-1-a"}
test var-14.1 {array names syntax} -body {
array names foo bar baz snafu
diff --git a/tests/winFCmd.test b/tests/winFCmd.test
index a808c82..28a08fb 100644
--- a/tests/winFCmd.test
+++ b/tests/winFCmd.test
@@ -1078,6 +1078,15 @@ test winFCmd-12.6 {ConvertFileNameFormat: absolute path with drive} -setup {
} -cleanup {
file delete -force -- c:/td1
} -result {c:/td1}
+test winFCmd-12.6.2 {ConvertFileNameFormat: absolute path with drive (in temp folder)} -setup {
+ catch {file delete -force -- $::env(TEMP)/td1}
+} -constraints {win} -body {
+ createfile $::env(TEMP)/td1 {}
+ string equal [string tolower [file attributes $::env(TEMP)/td1 -longname]] \
+ [string tolower [file normalize $::env(TEMP)]/td1]
+} -cleanup {
+ file delete -force -- $::env(TEMP)/td1
+} -result 1
test winFCmd-12.7 {ConvertFileNameFormat} -body {
string tolower [file attributes //bisque/tcl/ws -longname]
} -constraints {nonPortable win} -result {//bisque/tcl/ws}
diff --git a/tests/winPipe.test b/tests/winPipe.test
index 9c6f94d..9402db1 100644
--- a/tests/winPipe.test
+++ b/tests/winPipe.test
@@ -308,9 +308,54 @@ test winpipe-6.2 {PipeSetupProc & PipeCheckProc: write threads} \
lappend x [catch {close $f} msg] $msg
} {writable timeout 0 {}}
-set path(echoArgs.tcl) [makeFile {
- puts "[list $argv0 $argv]"
-} echoArgs.tcl]
+proc _testExecArgs {single args} {
+ variable path
+ if {![info exists path(echoArgs.tcl)] || ![file exists $path(echoArgs.tcl)]} {
+ set path(echoArgs.tcl) [makeFile {
+ puts "[list [file tail $argv0] {*}$argv]"
+ } echoArgs.tcl]
+ }
+ if {![info exists path(echoArgs.bat)] || ![file exists $path(echoArgs.bat)]} {
+ set path(echoArgs.bat) [makeFile "@[file native [interpreter]] $path(echoArgs.tcl) %*" "echoArgs.bat"]
+ }
+ set cmds [list [list [interpreter] $path(echoArgs.tcl)]]
+ if {!($single & 2)} {
+ lappend cmds [list $path(echoArgs.bat)]
+ } else {
+ if {![info exists path(echoArgs2.bat)] || ![file exists $path(echoArgs2.bat)]} {
+ file mkdir [file join [temporaryDirectory] test(Dir)Check]
+ set path(echoArgs2.bat) [makeFile "@[file native [interpreter]] $path(echoArgs.tcl) %*" \
+ "test(Dir)Check/echo(Cmd)Test Args & Batch.bat"]
+ }
+ lappend cmds [list $path(echoArgs2.bat)]
+ }
+ set broken {}
+ foreach args $args {
+ if {$single & 1} {
+ # enclose single test-arg between 1st/3rd to be sure nothing is truncated
+ # (e. g. to cover unexpected trim by nts-zero case, and args don't recombined):
+ set args [list "1st" $args "3rd"]
+ }
+ set args [list {*}$args]; # normalized canonical list
+ foreach cmd $cmds {
+ set e [linsert $args 0 [file tail $path(echoArgs.tcl)]]
+ tcltest::DebugPuts 4 " ## test exec [file extension [lindex $cmd 0]] ($cmd) for\n ## $args"
+ if {[catch {
+ exec {*}$cmd {*}$args
+ } r]} {
+ set r "ERROR: $r"
+ }
+ if {$r ne $e} {
+ append broken "\[ERROR\]: exec [file extension [lindex $cmd 0]] on $args\n -- result:\n$r\n -- expected:\n$e\n"
+ }
+ if {$single & 8} {
+ # if test exe only:
+ break
+ }
+ }
+ }
+ return $broken
+}
### validate the raw output of BuildCommandLine().
###
@@ -369,65 +414,178 @@ test winpipe-7.18 {BuildCommandLine: special chars #5} {win exec} {
exec $env(COMSPEC) /c echo foo \} bar
} "foo \} bar"
+set injectList {
+ {test"whoami} {test""whoami}
+ {test"""whoami} {test""""whoami}
+
+ "test\"whoami\\" "test\"\"whoami\\"
+ "test\"\"\"whoami\\" "test\"\"\"\"whoami\\"
+
+ {test\\&\\test} {test"\\&\\test}
+ {"test\\&\\test} {"test"\\&\\"test"}
+ {test\\"&"\\test} {test"\\"&"\\test}
+ {"test\\"&"\\test} {"test"\\"&"\\"test"}
+
+ {test\"&whoami} {test"\"&whoami}
+ {test""\"&whoami} {test"""\"&whoami}
+ {test\"\&whoami} {test"\"\&whoami}
+ {test""\"\&whoami} {test"""\"\&whoami}
+
+ {test&whoami} {test|whoami}
+ {"test&whoami} {"test|whoami}
+ {test"&whoami} {test"|whoami}
+ {"test"&whoami} {"test"|whoami}
+ {""test"&whoami} {""test"|whoami}
+
+ {test&echo "} {test|echo "}
+ {"test&echo "} {"test|echo "}
+ {test"&echo "} {test"|echo "}
+ {"test"&echo "} {"test"|echo "}
+ {""test"&echo "} {""test"|echo "}
+
+ {test&echo ""} {test|echo ""}
+ {"test&echo ""} {"test|echo ""}
+ {test"&echo ""} {test"|echo ""}
+ {"test"&echo ""} {"test"|echo ""}
+ {""test"&echo ""} {""test"|echo ""}
+
+ {test>whoami} {test<whoami}
+ {"test>whoami} {"test<whoami}
+ {test">whoami} {test"<whoami}
+ {"test">whoami} {"test"<whoami}
+ {""test">whoami} {""test"<whoami}
+ {test(whoami)} {test(whoami)}
+ {test"(whoami)} {test"(whoami)}
+ {test^whoami} {test^^echo ^^^}
+ {test"^whoami} {test"^^echo ^^^}
+ {test"^echo ^^^"} {test""^echo" ^^^"}
+
+ {test%USERDOMAIN%\%USERNAME%}
+ {test" %USERDOMAIN%\%USERNAME%}
+ {test%USERDOMAIN%\\%USERNAME%}
+ {test" %USERDOMAIN%\\%USERNAME%}
+ {test%USERDOMAIN%&%USERNAME%}
+ {test" %USERDOMAIN%&%USERNAME%}
+ {test%USERDOMAIN%\&\%USERNAME%}
+ {test" %USERDOMAIN%\&\%USERNAME%}
+
+ {test%USERDOMAIN%\&\test}
+ {test" %USERDOMAIN%\&\test}
+ {test%USERDOMAIN%\\&\\test}
+ {test" %USERDOMAIN%\\&\\test}
+
+ {test%USERDOMAIN%\&\"test}
+ {test" %USERDOMAIN%\&\"test}
+ {test%USERDOMAIN%\\&\\"test}
+ {test" %USERDOMAIN%\\&\\"test}
+}
+
### validate the pass-thru from BuildCommandLine() to the crt's parse_cmdline().
###
-test winpipe-8.1 {BuildCommandLine/parse_cmdline pass-thru: null arguments} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo "" bar
-} [list $path(echoArgs.tcl) [list foo {} bar]]
-test winpipe-8.2 {BuildCommandLine/parse_cmdline pass-thru: null arguments} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo {} bar
-} [list $path(echoArgs.tcl) [list foo {} bar]]
-test winpipe-8.3 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #1} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo "\"" bar
-} [list $path(echoArgs.tcl) [list foo "\"" bar]]
-test winpipe-8.4 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #2} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo {""} bar
-} [list $path(echoArgs.tcl) [list foo {""} bar]]
-test winpipe-8.5 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #3} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo "\" " bar
-} [list $path(echoArgs.tcl) [list foo "\" " bar]]
-test winpipe-8.6 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #4} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo {a="b"} bar
-} [list $path(echoArgs.tcl) [list foo {a="b"} bar]]
-test winpipe-8.7 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #5} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo {a = "b"} bar
-} [list $path(echoArgs.tcl) [list foo {a = "b"} bar]]
-test winpipe-8.8 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #6} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) {"hello"} {""hello""} {"""hello"""} {"\"hello\""} {he llo} {he " llo}
-} [list $path(echoArgs.tcl) [list {"hello"} {""hello""} {"""hello"""} {"\"hello\""} {he llo} {he " llo}]]
-test winpipe-8.9 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #1} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo \\ bar
-} [list $path(echoArgs.tcl) [list foo \\ bar]]
-test winpipe-8.10 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #2} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo \\\\ bar
-} [list $path(echoArgs.tcl) [list foo \\\\ bar]]
-test winpipe-8.11 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #3} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo \\\ \\ bar
-} [list $path(echoArgs.tcl) [list foo \\\ \\ bar]]
-test winpipe-8.12 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #4} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo \\\ \\\\ bar
-} [list $path(echoArgs.tcl) [list foo \\\ \\\\ bar]]
-test winpipe-8.13 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #5} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo \\\ \\\\\\ bar
-} [list $path(echoArgs.tcl) [list foo \\\ \\\\\\ bar]]
-test winpipe-8.14 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #6} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo \\\ \\\" bar
-} [list $path(echoArgs.tcl) [list foo \\\ \\\" bar]]
-test winpipe-8.15 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #7} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo \\\ \\\\\" bar
-} [list $path(echoArgs.tcl) [list foo \\\ \\\\\" bar]]
-test winpipe-8.16 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #8} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo \\\ \\\\\\\" bar
-} [list $path(echoArgs.tcl) [list foo \\\ \\\\\\\" bar]]
-test winpipe-8.17 {BuildCommandLine/parse_cmdline pass-thru: special chars #1} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo \{ bar
-} [list $path(echoArgs.tcl) [list foo \{ bar]]
-test winpipe-8.18 {BuildCommandLine/parse_cmdline pass-thru: special chars #2} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo \} bar
-} [list $path(echoArgs.tcl) [list foo \} bar]]
-test winpipe-8.19 {ensure parse_cmdline isn't doing wildcard replacement} {win exec} {
- exec [interpreter] $path(echoArgs.tcl) foo * makefile.?c bar
-} [list $path(echoArgs.tcl) [list foo * makefile.?c bar]]
+test winpipe-8.1 {BuildCommandLine/parse_cmdline pass-thru: dumped arguments are equal original} \
+-constraints {win exec} -body {
+ _testExecArgs 0 \
+ [list foo "" bar] \
+ [list foo {} bar] \
+ [list foo "\"" bar] \
+ [list foo {""} bar] \
+ [list foo "\" " bar] \
+ [list foo {a="b"} bar] \
+ [list foo {a = "b"} bar] \
+ [list {"hello"} {""hello""} {"""hello"""} {"\"hello\""} {he llo} {he " llo}] \
+ [list foo \\ bar] \
+ [list foo \\\\ bar] \
+ [list foo \\\ \\ bar] \
+ [list foo \\\ \\\\ bar] \
+ [list foo \\\ \\\\\\ bar] \
+ [list foo \\\ \\\" bar] \
+ [list foo \\\ \\\\\" bar] \
+ [list foo \\\ \\\\\\\" bar] \
+ [list foo \{ bar] \
+ [list foo \} bar] \
+ [list foo * makefile.?c bar]
+} -result {}
+
+test winpipe-8.2 {BuildCommandLine/parse_cmdline pass-thru: check injection on special meta-chars (particular)} \
+-constraints {win exec slowTest} -body {
+ _testExecArgs 1 {*}$injectList
+} -result {}
+
+test winpipe-8.3 {BuildCommandLine/parse_cmdline pass-thru: check injection on special meta-chars (jointly)} \
+-constraints {win exec} -body {
+ _testExecArgs 0 \
+ [list START {*}$injectList END] \
+ [list "START\"" {*}$injectList END] \
+ [list START {*}$injectList "\"END"] \
+ [list "START\"" {*}$injectList "\"END"]
+} -result {}
+
+test winpipe-8.4 {BuildCommandLine/parse_cmdline pass-thru: check injection on special meta-chars (command/jointly args)} \
+-constraints {win exec} -body {
+ _testExecArgs 2 \
+ [list START {*}$injectList END] \
+ [list "START\"" {*}$injectList END] \
+ [list START {*}$injectList "\"END"] \
+ [list "START\"" {*}$injectList "\"END"]
+} -result {}
+
+test winpipe-8.5 {BuildCommandLine/parse_cmdline pass-thru: check injection on special meta-chars (random mix)} \
+-constraints {win exec} -body {
+ set lst {}
+ set maps {
+ {\&|^<>!()%}
+ {\&|^<>!()% }
+ {"\&|^<>!()%}
+ {"\&|^<>!()% }
+ {"""""\\\\\&|^<>!()%}
+ {"""""\\\\\&|^<>!()% }
+ }
+ set i 0
+ time {
+ set args {[incr i].}
+ time {
+ set map [lindex $maps [expr {int(rand()*[llength $maps])}]]
+ # be sure arg has some prefix (avoid special handling, like |& etc)
+ set a {x}
+ while {[string length $a] < 50} {
+ append a [string index $map [expr {int(rand()*[string length $map])}]]
+ }
+ lappend args $a
+ } 20
+ lappend lst $args
+ } 10
+ _testExecArgs 0 {*}$lst
+} -result {} -cleanup {
+ unset -nocomplain lst args a map maps
+}
+
+set injectList {
+ "test\"\nwhoami" "test\"\"\nwhoami"
+ "test\"\"\"\nwhoami" "test\"\"\"\"\nwhoami"
+ "test;\n&echo \"" "\"test;\n&echo \""
+ "test\";\n&echo \"" "\"test\";\n&echo \""
+ "\"\"test\";\n&echo \""
+}
+
+test winpipe-8.6 {BuildCommandLine/parse_cmdline pass-thru: check new-line quoted in args} \
+-constraints {win exec} -body {
+ # test exe only, because currently there is no proper way to escape a new-line char resp.
+ # to supply a new-line to the batch-files within arguments (command line is truncated).
+ _testExecArgs 8 \
+ [list START {*}$injectList END] \
+ [list "START\"" {*}$injectList END] \
+ [list START {*}$injectList "\"END"] \
+ [list "START\"" {*}$injectList "\"END"]
+} -result {}
+
+test winpipe-8.7 {BuildCommandLine/parse_cmdline pass-thru: check new-line quoted in args (batch)} \
+-constraints {win exec knownBug} -body {
+ # this will fail if executed batch-file, because currently there is no proper way to escape a new-line char.
+ _testExecArgs 0 $injectList
+} -result {}
+
+
+rename _testExecArgs {}
# restore old values for env(TMP) and env(TEMP)
@@ -446,6 +604,8 @@ removeFile stdout
removeFile stderr
removeFile nothing
removeFile echoArgs.tcl
+removeFile echoArgs.bat
+file delete -force [file join [temporaryDirectory] test(Dir)Check]
::tcltest::cleanupTests
return