os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/tests/exec.test
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 # Commands covered:  exec
     2 #
     3 # This file contains a collection of tests for one or more of the Tcl
     4 # built-in commands.  Sourcing this file into Tcl runs the tests and
     5 # generates output for errors.  No output means no errors were found.
     6 #
     7 # Copyright (c) 1991-1994 The Regents of the University of California.
     8 # Copyright (c) 1994-1997 Sun Microsystems, Inc.
     9 # Copyright (c) 1998-1999 by Scriptics Corporation.
    10 #
    11 # See the file "license.terms" for information on usage and redistribution
    12 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    13 #
    14 # RCS: @(#) $Id: exec.test,v 1.16.2.7 2006/01/16 19:31:19 rmax Exp $
    15 
    16 package require tcltest 2
    17 namespace import -force ::tcltest::*
    18 
    19 # All tests require the "exec" command.
    20 # Skip them if exec is not defined.
    21 testConstraint exec [llength [info commands exec]]
    22 unset -nocomplain path
    23 set path(echo) [makeFile {
    24     puts -nonewline [lindex $argv 0]
    25     foreach str [lrange $argv 1 end] {
    26 	puts -nonewline " $str"
    27     }
    28     puts {}
    29     exit
    30 } echo]
    31 
    32 set path(cat) [makeFile {
    33     if {$argv == {}} {
    34 	set argv -
    35     }
    36     foreach name $argv {
    37 	if {$name == "-"} {
    38 	    set f stdin
    39 	} elseif {[catch {open $name r} f] != 0} {
    40 	    puts stderr $f
    41 	    continue
    42 	}
    43 	while {[eof $f] == 0} {
    44 	    puts -nonewline [read $f]
    45 	}
    46 	if {$f != "stdin"} {
    47 	    close $f
    48 	}
    49     }
    50     exit
    51 } cat]
    52 
    53 set path(wc) [makeFile {
    54     set data [read stdin]
    55     set lines [regsub -all "\n" $data {} dummy]
    56     set words [regsub -all "\[^ \t\n]+" $data {} dummy]
    57     set chars [string length $data]
    58     puts [format "%8.d%8.d%8.d" $lines $words $chars]
    59     exit
    60 } wc]
    61 
    62 set path(sh) [makeFile {
    63     if {[lindex $argv 0] != "-c"} {
    64 	error "sh: unexpected arguments $argv"
    65     }
    66     set cmd [lindex $argv 1]
    67     lappend cmd ";"
    68 
    69     set newcmd {}
    70     
    71     foreach arg $cmd {
    72 	if {$arg == ";"} {
    73 	    eval exec >@stdout 2>@stderr [list [info nameofexecutable]] $newcmd
    74 	    set newcmd {}
    75 	    continue
    76 	}
    77 	if {$arg == "1>&2"} {
    78 	    set arg >@stderr
    79 	}
    80 	lappend newcmd $arg
    81     }
    82     exit
    83 } sh]
    84 
    85 set path(sleep) [makeFile {
    86     after [expr $argv*1000]
    87     exit
    88 } sleep]
    89 
    90 set path(exit) [makeFile {
    91     exit $argv
    92 } exit]
    93 
    94 # Basic operations.
    95 
    96 test exec-1.1 {basic exec operation} {exec} {
    97     exec [interpreter] $path(echo) a b c
    98 } "a b c"
    99 test exec-1.2 {pipelining} {exec stdio} {
   100     exec [interpreter] $path(echo) a b c d | [interpreter] $path(cat) | [interpreter] $path(cat)
   101 } "a b c d"
   102 test exec-1.3 {pipelining} {exec stdio} {
   103     set a [exec [interpreter] $path(echo) a b c d | [interpreter] $path(cat) | [interpreter] $path(wc)]
   104     list [scan $a "%d %d %d" b c d] $b $c
   105 } {3 1 4}
   106 set arg {12345678901234567890123456789012345678901234567890}
   107 set arg "$arg$arg$arg$arg$arg$arg"
   108 test exec-1.4 {long command lines} {exec} {
   109     exec [interpreter] $path(echo) $arg
   110 } $arg
   111 set arg {}
   112 
   113 # I/O redirection: input from Tcl command.
   114 
   115 test exec-2.1 {redirecting input from immediate source} {exec stdio} {
   116     exec [interpreter] $path(cat) << "Sample text"
   117 } {Sample text}
   118 test exec-2.2 {redirecting input from immediate source} {exec stdio} {
   119     exec << "Sample text" [interpreter] $path(cat) | [interpreter] $path(cat)
   120 } {Sample text}
   121 test exec-2.3 {redirecting input from immediate source} {exec stdio} {
   122     exec [interpreter] $path(cat) << "Sample text" | [interpreter] $path(cat)
   123 } {Sample text}
   124 test exec-2.4 {redirecting input from immediate source} {exec stdio} {
   125     exec [interpreter] $path(cat) | [interpreter] $path(cat) << "Sample text"
   126 } {Sample text}
   127 test exec-2.5 {redirecting input from immediate source} {exec} {
   128     exec [interpreter] $path(cat) "<<Joined to arrows"
   129 } {Joined to arrows}
   130 test exec-2.6 {redirecting input from immediate source, with UTF} {exec} {
   131     # If this fails, it may give back:
   132     # "\uC3\uA9\uC3\uA0\uC3\uBC\uC3\uB1"
   133     # If it does, this means that the UTF -> external conversion did not 
   134     # occur before writing out the temp file.
   135     exec [interpreter] $path(cat) << "\uE9\uE0\uFC\uF1"
   136 } "\uE9\uE0\uFC\uF1"
   137 
   138 # I/O redirection: output to file.
   139 
   140 set path(gorp.file) [makeFile {} gorp.file]
   141 file delete $path(gorp.file)
   142 
   143 test exec-3.1 {redirecting output to file} {exec} {
   144     exec [interpreter] $path(echo) "Some simple words" > $path(gorp.file)
   145     exec [interpreter] $path(cat) $path(gorp.file)
   146 } "Some simple words"
   147 test exec-3.2 {redirecting output to file} {exec stdio} {
   148     exec [interpreter] $path(echo) "More simple words" | >$path(gorp.file) [interpreter] $path(cat) | [interpreter] $path(cat)
   149     exec [interpreter] $path(cat) $path(gorp.file)
   150 } "More simple words"
   151 test exec-3.3 {redirecting output to file} {exec stdio} {
   152     exec > $path(gorp.file) [interpreter] $path(echo) "Different simple words" | [interpreter] $path(cat) | [interpreter] $path(cat)
   153     exec [interpreter] $path(cat) $path(gorp.file)
   154 } "Different simple words"
   155 test exec-3.4 {redirecting output to file} {exec} {
   156     exec [interpreter] $path(echo) "Some simple words" >$path(gorp.file)
   157     exec [interpreter] $path(cat) $path(gorp.file)
   158 } "Some simple words"
   159 test exec-3.5 {redirecting output to file} {exec} {
   160     exec [interpreter] $path(echo) "First line" >$path(gorp.file)
   161     exec [interpreter] $path(echo) "Second line" >> $path(gorp.file)
   162     exec [interpreter] $path(cat) $path(gorp.file)
   163 } "First line\nSecond line"
   164 test exec-3.6 {redirecting output to file} {exec} {
   165     exec [interpreter] $path(echo) "First line" >$path(gorp.file)
   166     exec [interpreter] $path(echo) "Second line" >>$path(gorp.file)
   167     exec [interpreter] $path(cat) $path(gorp.file)
   168 } "First line\nSecond line"
   169 test exec-3.7 {redirecting output to file} {exec} {
   170     set f [open $path(gorp.file) w]
   171     puts $f "Line 1"
   172     flush $f
   173     exec [interpreter] $path(echo) "More text" >@ $f
   174     exec [interpreter] $path(echo) >@$f "Even more"
   175     puts $f "Line 3"
   176     close $f
   177     exec [interpreter] $path(cat) $path(gorp.file)
   178 } "Line 1\nMore text\nEven more\nLine 3"
   179 
   180 # I/O redirection: output and stderr to file.
   181 
   182 file delete $path(gorp.file)
   183 
   184 test exec-4.1 {redirecting output and stderr to file} {exec} {
   185     exec [interpreter] "$path(echo)" "test output" >& $path(gorp.file)
   186     exec [interpreter] "$path(cat)" "$path(gorp.file)"
   187 } "test output"
   188 test exec-4.2 {redirecting output and stderr to file} {exec} {
   189     list [exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" >&$path(gorp.file)] \
   190 	    [exec [interpreter] "$path(cat)" "$path(gorp.file)"]
   191 } {{} {foo bar}}
   192 test exec-4.3 {redirecting output and stderr to file} {exec} {
   193     exec [interpreter] $path(echo) "first line" > $path(gorp.file)
   194     list [exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" >>&$path(gorp.file)] \
   195 	    [exec [interpreter] "$path(cat)" "$path(gorp.file)"]
   196 } "{} {first line\nfoo bar}"
   197 test exec-4.4 {redirecting output and stderr to file} {exec} {
   198     set f [open "$path(gorp.file)" w]
   199     puts $f "Line 1"
   200     flush $f
   201     exec [interpreter] "$path(echo)" "More text" >&@ $f
   202     exec [interpreter] "$path(echo)" >&@$f "Even more"
   203     puts $f "Line 3"
   204     close $f
   205     exec [interpreter] "$path(cat)" "$path(gorp.file)"
   206 } "Line 1\nMore text\nEven more\nLine 3"
   207 test exec-4.5 {redirecting output and stderr to file} {exec} {
   208     set f [open "$path(gorp.file)" w]
   209     puts $f "Line 1"
   210     flush $f
   211     exec >&@ $f [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2"
   212     exec >&@$f [interpreter] "$path(sh)" -c "\"$path(echo)\" xyzzy 1>&2"
   213     puts $f "Line 3"
   214     close $f
   215     exec [interpreter] "$path(cat)" "$path(gorp.file)"
   216 } "Line 1\nfoo bar\nxyzzy\nLine 3"
   217 
   218 # I/O redirection: input from file.
   219 
   220 if { [set ::tcltest::testConstraints(exec)] } {
   221 exec [interpreter] $path(echo) "Just a few thoughts" > $path(gorp.file)
   222 }
   223 test exec-5.1 {redirecting input from file} {exec} {
   224     exec [interpreter] $path(cat) < $path(gorp.file)
   225 } {Just a few thoughts}
   226 test exec-5.2 {redirecting input from file} {exec stdio} {
   227     exec [interpreter] $path(cat) | [interpreter] $path(cat) < $path(gorp.file)
   228 } {Just a few thoughts}
   229 test exec-5.3 {redirecting input from file} {exec stdio} {
   230     exec [interpreter] $path(cat) < $path(gorp.file) | [interpreter] $path(cat)
   231 } {Just a few thoughts}
   232 test exec-5.4 {redirecting input from file} {exec stdio} {
   233     exec < $path(gorp.file) [interpreter] $path(cat) | [interpreter] $path(cat)
   234 } {Just a few thoughts}
   235 test exec-5.5 {redirecting input from file} {exec} {
   236     exec [interpreter] $path(cat) <$path(gorp.file)
   237 } {Just a few thoughts}
   238 test exec-5.6 {redirecting input from file} {exec} {
   239     set f [open $path(gorp.file) r]
   240     set result [exec [interpreter] $path(cat) <@ $f]
   241     close $f
   242     set result
   243 } {Just a few thoughts}
   244 test exec-5.7 {redirecting input from file} {exec} {
   245     set f [open $path(gorp.file) r]
   246     set result [exec <@$f [interpreter] $path(cat)]
   247     close $f
   248     set result
   249 } {Just a few thoughts}
   250 
   251 # I/O redirection: standard error through a pipeline.
   252 
   253 test exec-6.1 {redirecting stderr through a pipeline} {exec stdio} {
   254     exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar" |& [interpreter] "$path(cat)"
   255 } "foo bar"
   256 test exec-6.2 {redirecting stderr through a pipeline} {exec stdio} {
   257     exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" |& [interpreter] "$path(cat)"
   258 } "foo bar"
   259 test exec-6.3 {redirecting stderr through a pipeline} {exec stdio} {
   260     exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" \
   261 	|& [interpreter] "$path(sh)" -c "\"$path(echo)\" second msg 1>&2 ; \"$path(cat)\"" |& [interpreter] "$path(cat)"
   262 } "second msg\nfoo bar"
   263 
   264 # I/O redirection: combinations.
   265 
   266 set path(gorp.file2) [makeFile {} gorp.file2]
   267 file delete $path(gorp.file2)
   268 
   269 test exec-7.1 {multiple I/O redirections} {exec} {
   270     exec << "command input" > $path(gorp.file2) [interpreter] $path(cat) < $path(gorp.file)
   271     exec [interpreter] $path(cat) $path(gorp.file2)
   272 } {Just a few thoughts}
   273 test exec-7.2 {multiple I/O redirections} {exec} {
   274     exec < $path(gorp.file) << "command input" [interpreter] $path(cat)
   275 } {command input}
   276 
   277 # Long input to command and output from command.
   278 
   279 set a "0123456789 xxxxxxxxx abcdefghi ABCDEFGHIJK\n"
   280 set a [concat $a $a $a $a]
   281 set a [concat $a $a $a $a]
   282 set a [concat $a $a $a $a]
   283 set a [concat $a $a $a $a]
   284 test exec-8.1 {long input and output} {exec} {
   285     exec [interpreter] $path(cat) << $a
   286 } $a
   287 
   288 # More than 20 arguments to exec.
   289 
   290 test exec-8.2 {long input and output} {exec} {
   291     exec [interpreter] $path(echo) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   292 } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23}
   293 
   294 # Commands that return errors.
   295 
   296 test exec-9.1 {commands returning errors} {exec} {
   297     set x [catch {exec gorp456} msg]
   298     list $x [string tolower $msg] [string tolower $errorCode]
   299 } {1 {couldn't execute "gorp456": no such file or directory} {posix enoent {no such file or directory}}}
   300 test exec-9.2 {commands returning errors} {exec} {
   301     string tolower [list [catch {exec [interpreter] echo foo | foo123} msg] $msg $errorCode]
   302 } {1 {couldn't execute "foo123": no such file or directory} {posix enoent {no such file or directory}}}
   303 test exec-9.3 {commands returning errors} {exec stdio} {
   304     list [catch {exec [interpreter] $path(sleep) 1 | [interpreter] $path(exit) 43 | [interpreter] $path(sleep) 1} msg] $msg
   305 } {1 {child process exited abnormally}}
   306 test exec-9.4 {commands returning errors} {exec stdio} {
   307     list [catch {exec [interpreter] $path(exit) 43 | [interpreter] $path(echo) "foo bar"} msg] $msg
   308 } {1 {foo bar
   309 child process exited abnormally}}
   310 test exec-9.5 {commands returning errors} {exec stdio} {
   311     list [catch {exec gorp456 | [interpreter] echo a b c} msg] [string tolower $msg]
   312 } {1 {couldn't execute "gorp456": no such file or directory}}
   313 test exec-9.6 {commands returning errors} {exec} {
   314     list [catch {exec [interpreter] "$path(sh)" -c "\"$path(echo)\" error msg 1>&2"} msg] $msg
   315 } {1 {error msg}}
   316 test exec-9.7 {commands returning errors} {exec stdio} {
   317     list [catch {exec [interpreter] "$path(sh)" -c "\"$path(echo)\" error msg 1>&2" \
   318 		     | [interpreter] "$path(sh)" -c "\"$path(echo)\" error msg 1>&2"} msg] $msg
   319 } {1 {error msg
   320 error msg}}
   321 
   322 set path(err) [makeFile {} err]
   323 
   324 test exec-9.8 {commands returning errors} {exec} {
   325     set f [open $path(err) w]
   326     puts $f {
   327 	puts stdout out
   328 	puts stderr err
   329     }
   330     close $f
   331     list [catch {exec [interpreter] $path(err)} msg] $msg
   332 } {1 {out
   333 err}}
   334 
   335 # Errors in executing the Tcl command, as opposed to errors in the
   336 # processes that are invoked.
   337 
   338 test exec-10.1 {errors in exec invocation} {exec} {
   339     list [catch {exec} msg] $msg
   340 } {1 {wrong # args: should be "exec ?switches? arg ?arg ...?"}}
   341 test exec-10.2 {errors in exec invocation} {exec} {
   342     list [catch {exec | cat} msg] $msg
   343 } {1 {illegal use of | or |& in command}}
   344 test exec-10.3 {errors in exec invocation} {exec} {
   345     list [catch {exec cat |} msg] $msg
   346 } {1 {illegal use of | or |& in command}}
   347 test exec-10.4 {errors in exec invocation} {exec} {
   348     list [catch {exec cat | | cat} msg] $msg
   349 } {1 {illegal use of | or |& in command}}
   350 test exec-10.5 {errors in exec invocation} {exec} {
   351     list [catch {exec cat | |& cat} msg] $msg
   352 } {1 {illegal use of | or |& in command}}
   353 test exec-10.6 {errors in exec invocation} {exec} {
   354     list [catch {exec cat |&} msg] $msg
   355 } {1 {illegal use of | or |& in command}}
   356 test exec-10.7 {errors in exec invocation} {exec} {
   357     list [catch {exec cat <} msg] $msg
   358 } {1 {can't specify "<" as last word in command}}
   359 test exec-10.8 {errors in exec invocation} {exec} {
   360     list [catch {exec cat >} msg] $msg
   361 } {1 {can't specify ">" as last word in command}}
   362 test exec-10.9 {errors in exec invocation} {exec} {
   363     list [catch {exec cat <<} msg] $msg
   364 } {1 {can't specify "<<" as last word in command}}
   365 test exec-10.10 {errors in exec invocation} {exec} {
   366     list [catch {exec cat >>} msg] $msg
   367 } {1 {can't specify ">>" as last word in command}}
   368 test exec-10.11 {errors in exec invocation} {exec} {
   369     list [catch {exec cat >&} msg] $msg
   370 } {1 {can't specify ">&" as last word in command}}
   371 test exec-10.12 {errors in exec invocation} {exec} {
   372     list [catch {exec cat >>&} msg] $msg
   373 } {1 {can't specify ">>&" as last word in command}}
   374 test exec-10.13 {errors in exec invocation} {exec} {
   375     list [catch {exec cat >@} msg] $msg
   376 } {1 {can't specify ">@" as last word in command}}
   377 test exec-10.14 {errors in exec invocation} {exec} {
   378     list [catch {exec cat <@} msg] $msg
   379 } {1 {can't specify "<@" as last word in command}}
   380 test exec-10.15 {errors in exec invocation} {exec} {
   381     list [catch {exec cat < a/b/c} msg] [string tolower $msg]
   382 } {1 {couldn't read file "a/b/c": no such file or directory}}
   383 test exec-10.16 {errors in exec invocation} {exec} {
   384     list [catch {exec cat << foo > a/b/c} msg] [string tolower $msg]
   385 } {1 {couldn't write file "a/b/c": no such file or directory}}
   386 test exec-10.17 {errors in exec invocation} {exec} {
   387     list [catch {exec cat << foo > a/b/c} msg] [string tolower $msg]
   388 } {1 {couldn't write file "a/b/c": no such file or directory}}
   389 set f [open $path(gorp.file) w]
   390 test exec-10.18 {errors in exec invocation} {exec} {
   391     list [catch {exec cat <@ $f} msg] $msg
   392 } "1 {channel \"$f\" wasn't opened for reading}"
   393 close $f
   394 set f [open $path(gorp.file) r]
   395 test exec-10.19 {errors in exec invocation} {exec} {
   396     list [catch {exec cat >@ $f} msg] $msg
   397 } "1 {channel \"$f\" wasn't opened for writing}"
   398 close $f
   399 test exec-10.20 {errors in exec invocation} {exec} {
   400     list [catch {exec ~non_existent_user/foo/bar} msg] $msg
   401 } {1 {user "non_existent_user" doesn't exist}}
   402 test exec-10.21 {errors in exec invocation} {exec} {
   403     list [catch {exec [interpreter] true | ~xyzzy_bad_user/x | false} msg] $msg
   404 } {1 {user "xyzzy_bad_user" doesn't exist}}
   405 test exec-10.22 {errors in exec invocation} \
   406 -constraints exec \
   407 -returnCodes 1 \
   408 -body {exec echo test > ~non_existent_user/foo/bar} \
   409 -result {user "non_existent_user" doesn't exist}
   410 # Commands in background.
   411 
   412 test exec-11.1 {commands in background} {exec} {
   413     set x [lindex [time {exec [interpreter] $path(sleep) 2 &}] 0]
   414     expr $x<1000000
   415 } 1
   416 test exec-11.2 {commands in background} {exec} {
   417     list [catch {exec [interpreter] $path(echo) a &b} msg] $msg
   418 } {0 {a &b}}
   419 test exec-11.3 {commands in background} {exec} {
   420     llength [exec [interpreter] $path(sleep) 1 &]
   421 } 1
   422 test exec-11.4 {commands in background} {exec stdio} {
   423     llength [exec [interpreter] $path(sleep) 1 | [interpreter] $path(sleep) 1 | [interpreter] $path(sleep) 1 &]
   424 } 3
   425 test exec-11.5 {commands in background} {exec} {
   426     set f [open $path(gorp.file) w]
   427     puts $f [list catch [list exec [info nameofexecutable] $path(echo) foo &]]
   428     close $f
   429     string compare "foo" [exec [interpreter] $path(gorp.file)]
   430 } 0
   431 
   432 # Make sure that background commands are properly reaped when
   433 # they eventually die.
   434 
   435 if { [set ::tcltest::testConstraints(exec)] } {
   436 exec [interpreter] $path(sleep) 3
   437 }
   438 test exec-12.1 {reaping background processes} \
   439 	{exec unixOnly nonPortable} {
   440     for {set i 0} {$i < 20} {incr i} {
   441 	exec echo foo > /dev/null &
   442     }
   443     exec sleep 1
   444     catch {exec ps | fgrep "echo foo" | fgrep -v fgrep | wc} msg
   445     lindex $msg 0
   446 } 0
   447 test exec-12.2 {reaping background processes} \
   448 	{exec unixOnly nonPortable} {
   449     exec sleep 2 | sleep 2 | sleep 2 &
   450     catch {exec ps | fgrep -i "sleep" | fgrep -i -v fgrep | wc} msg
   451     set x [lindex $msg 0]
   452     exec sleep 3
   453     catch {exec ps | fgrep -i "sleep" | fgrep -i -v fgrep | wc} msg
   454     list $x [lindex $msg 0]
   455 } {3 0}
   456 test exec-12.3 {reaping background processes} \
   457 	{exec unixOnly nonPortable} {
   458     exec sleep 1000 &
   459     exec sleep 1000 &
   460     set x [exec ps | fgrep "sleep" | fgrep -v fgrep]
   461     set pids {}
   462     foreach i [split $x \n] {
   463 	lappend pids [lindex $i 0]
   464     }
   465     foreach i $pids {
   466 	catch {exec kill -STOP $i}
   467     }
   468     catch {exec ps | fgrep "sleep" | fgrep -v fgrep | wc} msg
   469     set x [lindex $msg 0]
   470 
   471     foreach i $pids {
   472 	catch {exec kill -KILL $i}
   473     }
   474     catch {exec ps | fgrep "sleep" | fgrep -v fgrep | wc} msg
   475     list $x [lindex $msg 0]
   476 } {2 0}
   477 
   478 # Make sure "errorCode" is set correctly.
   479 
   480 test exec-13.1 {setting errorCode variable} {exec} {
   481     list [catch {exec [interpreter] $path(cat) < a/b/c} msg] [string tolower $errorCode]
   482 } {1 {posix enoent {no such file or directory}}}
   483 test exec-13.2 {setting errorCode variable} {exec} {
   484     list [catch {exec [interpreter] $path(cat) > a/b/c} msg] [string tolower $errorCode]
   485 } {1 {posix enoent {no such file or directory}}}
   486 test exec-13.3 {setting errorCode variable} {exec} {
   487     set x [catch {exec _weird_cmd_} msg]
   488     list $x [string tolower $msg] [lindex $errorCode 0] \
   489 	    [string tolower [lrange $errorCode 2 end]]
   490 } {1 {couldn't execute "_weird_cmd_": no such file or directory} POSIX {{no such file or directory}}}
   491 
   492 test exec-13.4 {extended exit result codes} {
   493     -constraints {win}
   494     -setup {
   495         set tmp [makeFile {exit 0x00000101} tmpfile.exec-13.4]
   496     }
   497     -body {
   498         list [catch {exec [interpreter] $tmp} err]\
   499             [lreplace $::errorCode 1 1 {}]
   500     }
   501     -cleanup {
   502         removeFile $tmp
   503     }
   504     -result {1 {CHILDSTATUS {} 257}}
   505 }
   506 
   507 test exec-13.5 {extended exit result codes: max value} {
   508     -constraints {win}
   509     -setup {
   510         set tmp [makeFile {exit 0x3fffffff} tmpfile.exec-13.5]
   511     }
   512     -body {
   513         list [catch {exec [interpreter] $tmp} err]\
   514             [lreplace $::errorCode 1 1 {}]
   515     }
   516     -cleanup {
   517         removeFile $tmp
   518     }
   519     -result {1 {CHILDSTATUS {} 1073741823}}
   520 }
   521 
   522 test exec-13.6 {extended exit result codes: signalled} {   
   523     -constraints {win}
   524     -setup {
   525         set tmp [makeFile {exit 0xffffffff} tmpfile.exec-13.6]
   526     }
   527     -body {
   528         list [catch {exec [interpreter] $tmp} err]\
   529             [lreplace $::errorCode 1 1 {}]
   530     }
   531     -cleanup {
   532         removeFile $tmp
   533     }
   534     -result {1 {CHILDKILLED {} SIGABRT SIGABRT}}
   535 }
   536 
   537 # Switches before the first argument
   538 
   539 test exec-14.1 {-keepnewline switch} {exec} {
   540     exec -keepnewline [interpreter] $path(echo) foo
   541 } "foo\n"
   542 test exec-14.2 {-keepnewline switch} {exec} {
   543     list [catch {exec -keepnewline} msg] $msg
   544 } {1 {wrong # args: should be "exec ?switches? arg ?arg ...?"}}
   545 test exec-14.3 {unknown switch} {exec} {
   546     list [catch {exec -gorp} msg] $msg
   547 } {1 {bad switch "-gorp": must be -keepnewline or --}}
   548 test exec-14.4 {-- switch} {exec} {
   549     list [catch {exec -- -gorp} msg] [string tolower $msg]
   550 } {1 {couldn't execute "-gorp": no such file or directory}}
   551 
   552 # Redirecting standard error separately from standard output
   553 
   554 test exec-15.1 {standard error redirection} {exec} {
   555     exec [interpreter] "$path(echo)" "First line" > "$path(gorp.file)"
   556     list [exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" 2> "$path(gorp.file)"] \
   557 	    [exec [interpreter] "$path(cat)" "$path(gorp.file)"]
   558 } {{} {foo bar}}
   559 test exec-15.2 {standard error redirection} {exec stdio} {
   560     list [exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" \
   561 		| [interpreter] "$path(echo)" biz baz >$path(gorp.file) 2> "$path(gorp.file2)"] \
   562 	    [exec [interpreter] "$path(cat)" "$path(gorp.file)"] \
   563 	    [exec [interpreter] "$path(cat)" "$path(gorp.file2)"]
   564 } {{} {biz baz} {foo bar}}
   565 test exec-15.3 {standard error redirection} {exec stdio} {
   566     list [exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" \
   567 	        | [interpreter] "$path(echo)" biz baz 2>$path(gorp.file) > "$path(gorp.file2)"] \
   568 	    [exec [interpreter] "$path(cat)" "$path(gorp.file)"] \
   569 	    [exec [interpreter] "$path(cat)" "$path(gorp.file2)"]
   570 } {{} {foo bar} {biz baz}}
   571 test exec-15.4 {standard error redirection} {exec} {
   572     set f [open "$path(gorp.file)" w]
   573     puts $f "Line 1"
   574     flush $f
   575     exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" 2>@ $f
   576     puts $f "Line 3"
   577     close $f
   578     exec [interpreter] "$path(cat)" "$path(gorp.file)"
   579 } {Line 1
   580 foo bar
   581 Line 3}
   582 test exec-15.5 {standard error redirection} {exec} {
   583     exec [interpreter] "$path(echo)" "First line" > "$path(gorp.file)"
   584     exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" 2>> "$path(gorp.file)"
   585     exec [interpreter] "$path(cat)" "$path(gorp.file)"
   586 } {First line
   587 foo bar}
   588 test exec-15.6 {standard error redirection} {exec stdio} {
   589     exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" > "$path(gorp.file2)" 2> "$path(gorp.file)" \
   590 	    >& "$path(gorp.file)" 2> "$path(gorp.file2)" | [interpreter] "$path(echo)" biz baz
   591     list [exec [interpreter] "$path(cat)" "$path(gorp.file)"] [exec [interpreter] "$path(cat)" "$path(gorp.file2)"]
   592 } {{biz baz} {foo bar}}
   593 test exec-15.7 {standard error redirection 2>@1} {exec stdio} {
   594     # This redirects stderr output into normal result output from exec
   595     exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" 2>@1
   596 } {foo bar}
   597 
   598 test exec-16.1 {flush output before exec} {exec} {
   599     set f [open $path(gorp.file) w]
   600     puts $f "First line"
   601     exec [interpreter] $path(echo) "Second line" >@ $f
   602     puts $f "Third line"
   603     close $f
   604     exec [interpreter] $path(cat) $path(gorp.file)
   605 } {First line
   606 Second line
   607 Third line}
   608 test exec-16.2 {flush output before exec} {exec} {
   609     set f [open $path(gorp.file) w]
   610     puts $f "First line"
   611     exec [interpreter] << {puts stderr {Second line}} >&@ $f > $path(gorp.file2)
   612     puts $f "Third line"
   613     close $f
   614     exec [interpreter] $path(cat) $path(gorp.file)
   615 } {First line
   616 Second line
   617 Third line}
   618 
   619 set path(script) [makeFile {} script]
   620 
   621 test exec-17.1 { inheriting standard I/O } {exec} {
   622     set f [open $path(script) w]
   623     puts -nonewline $f {close stdout
   624 	set f [}
   625     puts $f [list open $path(gorp.file) w]]
   626     puts $f [list catch \
   627 	    [list exec [info nameofexecutable] $path(echo) foobar &]]
   628     puts $f [list exec [info nameofexecutable] $path(sleep) 2]
   629     puts $f {close $f}
   630     close $f
   631     catch {exec [interpreter] $path(script)} result
   632     set f [open $path(gorp.file) r]
   633     lappend result [read $f]
   634     close $f
   635     set result
   636 } {{foobar
   637 }}
   638 
   639 test exec-18.1 { exec cat deals with weird file names} {exec tempNotWin} {
   640     # This is cross-platform, but the cat isn't predictably correct on
   641     # Windows.
   642     set f "foo\[\{blah"
   643     set path(fooblah) [makeFile {} $f]
   644     set fout [open $path(fooblah) w]
   645     puts $fout "contents"
   646     close $fout
   647     set res [list [catch {exec cat $path(fooblah)} msg] $msg]
   648     removeFile $f
   649     set res
   650 } {0 contents}
   651 
   652 # Note that this test cannot be adapted to work on Windows; that platform has
   653 # no kernel support for an analog of O_APPEND.
   654 test exec-19.1 {exec >> uses O_APPEND} {
   655     -constraints {exec unix}
   656     -setup {
   657 	set tmpfile [makeFile {0} tmpfile.exec-19.1]
   658     }
   659     -body {
   660 	# Note that we have to allow for the current contents of the
   661 	# temporary file, which is why the result is 14 and not 12
   662 	exec /bin/sh -c \
   663 	    {for a in 1 2 3; do sleep 1; echo $a; done} >>$tmpfile &
   664 	exec /bin/sh -c \
   665 	    {for a in a b c; do sleep 1; echo $a; done} >>$tmpfile &
   666 	# The above two shell invokations take about 3 seconds to
   667 	# finish, so allow 5s (in case the machine is busy)
   668 	after 5000
   669 	# Check that no bytes have got lost through mixups with
   670 	# overlapping appends, which is only guaranteed to work when
   671 	# we set O_APPEND on the file descriptor in the [exec >>...]
   672 	file size $tmpfile
   673     }
   674     -cleanup {
   675 	removeFile $tmpfile
   676     }
   677     -result 14
   678 }
   679 
   680 # cleanup
   681 
   682 foreach file {script gorp.file gorp.file2 echo cat wc sh sleep exit err} {
   683     removeFile $file
   684 }
   685 unset -nocomplain path
   686 
   687 ::tcltest::cleanupTests
   688 return