sl@0: # This file contains a collection of tests for generic/tclMain.c.
sl@0: #
sl@0: # RCS: @(#) $Id$
sl@0: 
sl@0: if {[catch {package require tcltest 2.0.2}]} {
sl@0:     puts stderr "Skipping tests in [info script]. tcltest 2.0.2 required."
sl@0:     return
sl@0: }
sl@0: 
sl@0: namespace eval ::tcl::test::main {
sl@0: 
sl@0:     namespace import ::tcltest::test
sl@0:     namespace import ::tcltest::testConstraint
sl@0:     namespace import ::tcltest::interpreter
sl@0:     namespace import ::tcltest::cleanupTests
sl@0:     namespace import ::tcltest::makeFile
sl@0:     namespace import ::tcltest::removeFile
sl@0:     namespace import ::tcltest::temporaryDirectory
sl@0:     namespace import ::tcltest::workingDirectory
sl@0: 
sl@0:     # Is [exec] defined?
sl@0:     testConstraint exec [llength [info commands exec]]
sl@0: 
sl@0:     # Is the Tcltest package loaded?
sl@0:     #	- that is, the special C-coded testing commands in tclTest.c
sl@0:     #   - tests use testing commands introduced in Tcltest 8.4
sl@0:     testConstraint Tcltest [expr {
sl@0: 	[llength [package provide Tcltest]]
sl@0: 	&& [package vsatisfies [package provide Tcltest] 8.4]}]
sl@0: 
sl@0:     # Procedure to simulate interactive typing of commands, line by line
sl@0:     proc type {chan script} {
sl@0: 	foreach line [split $script \n] {
sl@0: 	    if {[catch {
sl@0: 	        puts $chan $line
sl@0: 	        flush $chan
sl@0: 	    }]} {
sl@0: 		return
sl@0: 	    }
sl@0: 	    # Grrr... Behavior depends on this value.
sl@0: 	    after 1000
sl@0: 	}
sl@0:     }
sl@0: 
sl@0:     cd [temporaryDirectory]
sl@0:     # Tests Tcl_Main-1.*: variable initializations
sl@0: 
sl@0:     test Tcl_Main-1.1 {
sl@0: 	Tcl_Main: startup script - normal
sl@0:     } -constraints {
sl@0: 	stdio
sl@0:     } -setup {
sl@0: 	makeFile {puts [list $argv0 $argv $tcl_interactive]} script
sl@0: 	catch {set f [open "|[list [interpreter] script]" r]}
sl@0:     } -body {
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	removeFile script
sl@0:     } -result [list script {} 0]\n
sl@0: 
sl@0:     test Tcl_Main-1.2 {
sl@0: 	Tcl_Main: startup script - can't begin with '-'
sl@0:     } -constraints {
sl@0: 	stdio
sl@0:     } -setup {
sl@0: 	makeFile {puts [list $argv0 $argv $tcl_interactive]} -script
sl@0: 	catch {set f [open "|[list [interpreter] -script]" w+]}
sl@0:     } -body {
sl@0: 	puts $f {puts [list $argv0 $argv $tcl_interactive]; exit}
sl@0: 	flush $f
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	removeFile -script
sl@0:     } -result [list [interpreter] -script 0]\n
sl@0: 
sl@0:     test Tcl_Main-1.3 {
sl@0: 	Tcl_Main: encoding of arguments: done by system encoding
sl@0: 	Note the shortcoming explained in Tcl Feature Request 491789
sl@0:     } -constraints {
sl@0: 	stdio
sl@0:     } -setup {
sl@0: 	makeFile {puts [list $argv0 $argv $tcl_interactive]} script
sl@0: 	catch {set f [open "|[list [interpreter] script \u00c0]" r]}
sl@0:     } -body {
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	removeFile script
sl@0:     } -result [list script [list [encoding convertfrom [encoding system] \
sl@0: 	[encoding convertto [encoding system] \u00c0]]] 0]\n
sl@0: 
sl@0:     test Tcl_Main-1.4 {
sl@0: 	Tcl_Main: encoding of arguments: done by system encoding
sl@0: 	Note the shortcoming explained in Tcl Feature Request 491789
sl@0:     } -constraints {
sl@0: 	stdio tempNotWin
sl@0:     } -setup {
sl@0: 	makeFile {puts [list $argv0 $argv $tcl_interactive]} script
sl@0: 	catch {set f [open "|[list [interpreter] script \u20ac]" r]}
sl@0:     } -body {
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	removeFile script
sl@0:     } -result [list script [list [encoding convertfrom [encoding system] \
sl@0: 	[encoding convertto [encoding system] \u20ac]]] 0]\n
sl@0: 
sl@0:     test Tcl_Main-1.5 {
sl@0: 	Tcl_Main: encoding of script name: system encoding loss
sl@0: 	Note the shortcoming explained in Tcl Feature Request 491789
sl@0:     } -constraints {
sl@0: 	stdio
sl@0:     } -setup {
sl@0: 	makeFile {puts [list $argv0 $argv $tcl_interactive]} \u00c0
sl@0: 	catch {set f [open "|[list [interpreter] \u00c0]" r]}
sl@0:     } -body {
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	removeFile \u00c0
sl@0:     } -result [list [list [encoding convertfrom [encoding system] \
sl@0: 	[encoding convertto [encoding system] \u00c0]]] {} 0]\n
sl@0: 
sl@0:     test Tcl_Main-1.6 {
sl@0: 	Tcl_Main: encoding of script name: system encoding loss
sl@0: 	Note the shortcoming explained in Tcl Feature Request 491789
sl@0:     } -constraints {
sl@0: 	stdio tempNotWin
sl@0:     } -setup {
sl@0: 	makeFile {puts [list $argv0 $argv $tcl_interactive]} \u20ac
sl@0: 	catch {set f [open "|[list [interpreter] \u20ac]" r]}
sl@0:     } -body {
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	removeFile \u20ac
sl@0:     } -result [list [list [encoding convertfrom [encoding system] \
sl@0: 	[encoding convertto [encoding system] \u20ac]]] {} 0]\n
sl@0: 
sl@0:     # Tests Tcl_Main-2.*: application-initialization procedure
sl@0: 
sl@0:     test Tcl_Main-2.1 {
sl@0: 	Tcl_Main: appInitProc returns error
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	makeFile {puts "In script"} script
sl@0:     } -body {
sl@0: 	exec [interpreter] script -appinitprocerror >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile script
sl@0:     } -result "application-specific initialization failed: \nIn script\n"
sl@0: 
sl@0:     test Tcl_Main-2.2 {
sl@0: 	Tcl_Main: appInitProc returns error
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {puts "In script"} -appinitprocerror >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "application-specific initialization failed: \nIn script\n"
sl@0: 
sl@0:     test Tcl_Main-2.3 {
sl@0: 	Tcl_Main: appInitProc deletes interp
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	makeFile {puts "In script"} script
sl@0:     } -body {
sl@0: 	exec [interpreter] script -appinitprocdeleteinterp >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile script
sl@0:     } -result "application-specific initialization failed: \n"
sl@0: 
sl@0:     test Tcl_Main-2.4 {
sl@0: 	Tcl_Main: appInitProc deletes interp
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {puts "In script"} \
sl@0: 		-appinitprocdeleteinterp >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "application-specific initialization failed: \n"
sl@0: 
sl@0:     test Tcl_Main-2.5 {
sl@0: 	Tcl_Main: appInitProc closes stderr
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {puts "In script"} \
sl@0: 		-appinitprocclosestderr >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "In script\n"
sl@0: 
sl@0:     # Tests Tcl_Main-3.*: startup script evaluation
sl@0: 
sl@0:     test Tcl_Main-3.1 {
sl@0: 	Tcl_Main: startup script does not exist
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -setup {
sl@0: 	if {[file exists no-such-file]} {
sl@0: 	    error "Can't run test Tcl_Main-3.1\
sl@0: 		    where a file named \"no-such-file\" exists"
sl@0: 	}
sl@0:     } -body {
sl@0: 	set code [catch {exec [interpreter] no-such-file >& result} result]
sl@0: 	set f [open result]
sl@0: 	list $code $result [read $f]
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -match glob -result [list 1 {child process exited abnormally} \
sl@0: 	{couldn't read file "no-such-file":*}]
sl@0: 
sl@0:     test Tcl_Main-3.2 {
sl@0: 	Tcl_Main: startup script raises error
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -setup {
sl@0: 	makeFile {error ERROR} script
sl@0:     } -body {
sl@0: 	set code [catch {exec [interpreter] script >& result} result]
sl@0: 	set f [open result]
sl@0: 	list $code $result [read $f]
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile script
sl@0:     } -match glob -result [list 1 {child process exited abnormally} \
sl@0: 	"ERROR\n    while executing*"]
sl@0: 
sl@0:     test Tcl_Main-3.3 {
sl@0: 	Tcl_Main: startup script closes stderr
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -setup {
sl@0: 	makeFile {close stderr; error ERROR} script
sl@0:     } -body {
sl@0: 	set code [catch {exec [interpreter] script >& result} result]
sl@0: 	set f [open result]
sl@0: 	list $code $result [read $f]
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile script
sl@0:     } -result [list 1 {child process exited abnormally} {}]
sl@0: 
sl@0:     test Tcl_Main-3.4 {
sl@0: 	Tcl_Main: startup script holds incomplete script
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -setup {
sl@0: 	makeFile "if 1 \{" script
sl@0:     } -body {
sl@0: 	set code [catch {exec [interpreter] script >& result} result]
sl@0: 	set f [open result]
sl@0: 	join [list $code $result [read $f]] \n
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile script
sl@0:     } -match glob -result [join [list 1 {child process exited abnormally}\
sl@0: 	"missing close-brace\n    while executing*"] \n]
sl@0: 
sl@0:     test Tcl_Main-3.5 {
sl@0: 	Tcl_Main: startup script sets main loop
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	makeFile {
sl@0: 		rename exit _exit
sl@0: 		proc exit {code} {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		after 0 {
sl@0: 			puts event
sl@0: 			testexitmainloop
sl@0: 		}
sl@0: 		testexithandler create 0
sl@0: 		testsetmainloop
sl@0: 	} script
sl@0:     } -body {
sl@0: 	exec [interpreter] script >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile script
sl@0:     } -result "event\nExit MainLoop\nIn exit\neven 0\n"
sl@0: 
sl@0:     test Tcl_Main-3.6 {
sl@0: 	Tcl_Main: startup script sets main loop and closes stdin
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	makeFile {
sl@0: 		close stdin
sl@0: 		testsetmainloop
sl@0: 		rename exit _exit
sl@0: 		proc exit {code} {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		after 0 {
sl@0: 			puts event
sl@0: 			testexitmainloop
sl@0: 		}
sl@0: 		testexithandler create 0
sl@0: 	} script
sl@0:     } -body {
sl@0: 	exec [interpreter] script >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile script
sl@0:     } -result "event\nExit MainLoop\nIn exit\neven 0\n"
sl@0: 
sl@0:     test Tcl_Main-3.7 {
sl@0: 	Tcl_Main: startup script deletes interp
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	makeFile {
sl@0: 		rename exit _exit
sl@0: 		proc exit {code} {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		testexithandler create 0
sl@0: 		testinterpdelete {}
sl@0: 	} script
sl@0:     } -body {
sl@0: 	exec [interpreter] script >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile script
sl@0:     } -result "even 0\n"
sl@0: 
sl@0:     test Tcl_Main-3.8 {
sl@0: 	Tcl_Main: startup script deletes interp and sets mainloop
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	makeFile {
sl@0: 		testsetmainloop
sl@0: 		rename exit _exit
sl@0: 		proc exit {code} {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		testexitmainloop
sl@0: 		testexithandler create 0
sl@0: 		testinterpdelete {}
sl@0: 	} script
sl@0:     } -body {
sl@0: 	exec [interpreter] script >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile script
sl@0:     } -result "Exit MainLoop\neven 0\n"
sl@0: 
sl@0:     test Tcl_Main-3.9 {
sl@0: 	Tcl_Main: startup script can set tcl_interactive without limit
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -setup {
sl@0: 	makeFile {set tcl_interactive foo} script
sl@0:     } -body {
sl@0: 	exec [interpreter] script >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile script
sl@0:     } -result {}
sl@0: 
sl@0:     # Tests Tcl_Main-4.*: rc file evaluation
sl@0: 
sl@0:     test Tcl_Main-4.1 {
sl@0: 	Tcl_Main: rcFile evaluation deletes interp
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	set rc [makeFile {testinterpdelete {}} rc]
sl@0:     } -body {
sl@0: 	exec [interpreter] << {puts "In script"} \
sl@0: 		-appinitprocsetrcfile $rc >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile rc
sl@0:     } -result "application-specific initialization failed: \n"
sl@0: 
sl@0:     test Tcl_Main-4.2 {
sl@0: 	Tcl_Main: rcFile evaluation closes stdin
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	set rc [makeFile {close stdin} rc]
sl@0:     } -body {
sl@0: 	exec [interpreter] << {puts "In script"} \
sl@0: 		-appinitprocsetrcfile $rc >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile rc
sl@0:     } -result "application-specific initialization failed: \n"
sl@0: 
sl@0:     test Tcl_Main-4.3 {
sl@0: 	Tcl_Main: rcFile evaluation closes stdin and sets main loop
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	set rc [makeFile {
sl@0: 		close stdin
sl@0: 		testsetmainloop
sl@0: 		after 0 testexitmainloop
sl@0: 		testexithandler create 0
sl@0: 		rename exit _exit
sl@0: 		proc exit code {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 	} rc]
sl@0:     } -body {
sl@0: 	exec [interpreter] << {puts "In script"} \
sl@0: 		-appinitprocsetrcfile $rc >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile rc
sl@0:     } -result "application-specific initialization failed:\
sl@0: 	\nExit MainLoop\nIn exit\neven 0\n"
sl@0: 
sl@0:     test Tcl_Main-4.4 {
sl@0: 	Tcl_Main: rcFile evaluation sets main loop
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	set rc [makeFile {
sl@0: 		testsetmainloop
sl@0: 		after 0 testexitmainloop
sl@0: 		testexithandler create 0
sl@0: 		rename exit _exit
sl@0: 		proc exit code {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 	} rc]
sl@0:     } -body {
sl@0: 	exec [interpreter] << {} \
sl@0: 		-appinitprocsetrcfile $rc >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0: 	removeFile rc
sl@0:     } -result "application-specific initialization failed:\
sl@0: 	\nExit MainLoop\nIn exit\neven 0\n"
sl@0: 
sl@0:     test Tcl_Main-4.5 {
sl@0: 	Tcl_Main: Bug 1481986
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	set rc [makeFile {
sl@0: 		testsetmainloop
sl@0: 		after 0 {puts "Event callback"}
sl@0: 	} rc]
sl@0:     } -body {
sl@0: 	set f [open "|[list [interpreter] -appinitprocsetrcfile $rc]" w+]
sl@0: 	after 1000
sl@0: 	type $f {puts {Interactive output}
sl@0: 	    exit
sl@0: 	}
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	catch {close $f}
sl@0: 	removeFile rc
sl@0:     } -result "Event callback\nInteractive output\n"
sl@0: 
sl@0:     # Tests Tcl_Main-5.*: interactive operations
sl@0: 
sl@0:     test Tcl_Main-5.1 {
sl@0: 	Tcl_Main: tcl_interactive must be boolean
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {set tcl_interactive foo} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "can't set \"tcl_interactive\":\
sl@0: 	     variable must have boolean value\n"
sl@0: 
sl@0:     test Tcl_Main-5.2 {
sl@0: 	Tcl_Main able to handle non-blocking stdin
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -setup {
sl@0: 	catch {set f [open "|[list [interpreter]]" w+]}
sl@0:     } -body {
sl@0: 	type $f {
sl@0: 	    fconfigure stdin -blocking 0
sl@0: 	    puts SUCCESS
sl@0: 	}
sl@0: 	list [catch {gets $f} line] $line
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0:     } -result [list 0 SUCCESS]
sl@0: 
sl@0:     test Tcl_Main-5.3 {
sl@0: 	Tcl_Main handles stdin EOF in mid-command
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -setup {
sl@0: 	catch {set f [open "|[list [interpreter]]" w+]}
sl@0: 	catch {fconfigure $f -blocking 0}
sl@0:     } -body {
sl@0: 	type $f "fconfigure stdin -eofchar \\032
sl@0: 	    if 1 \{\n\032"
sl@0: 	variable wait
sl@0: 	fileevent $f readable \
sl@0: 		[list set [namespace which -variable wait] "child exit"]
sl@0: 	set id [after 2000 [list set [namespace which -variable wait] timeout]]
sl@0: 	vwait [namespace which -variable wait]
sl@0: 	after cancel $id
sl@0: 	set wait
sl@0:     } -cleanup {
sl@0: 	if {[string equal timeout $wait]
sl@0: 		&& [string equal unix $::tcl_platform(platform)]} {
sl@0: 	    exec kill [pid $f]
sl@0: 	}
sl@0: 	close $f
sl@0:     } -result {child exit}
sl@0: 
sl@0:     test Tcl_Main-5.4 {
sl@0: 	Tcl_Main handles stdin EOF in mid-command
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -setup {
sl@0: 	set cmd {makeFile "if 1 \{" script}
sl@0: 	catch {set f [open "|[list [interpreter]] < [list [eval $cmd]]" r]}
sl@0: 	catch {fconfigure $f -blocking 0}
sl@0:     } -body {
sl@0: 	variable wait
sl@0: 	fileevent $f readable \
sl@0: 		[list set [namespace which -variable wait] "child exit"]
sl@0: 	set id [after 2000 [list set [namespace which -variable wait] timeout]]
sl@0: 	vwait [namespace which -variable wait]
sl@0: 	after cancel $id
sl@0: 	set wait
sl@0:     } -cleanup {
sl@0: 	if {[string equal timeout $wait]
sl@0: 		&& [string equal unix $::tcl_platform(platform)]} {
sl@0: 	    exec kill [pid $f]
sl@0: 	}
sl@0: 	close $f
sl@0: 	removeFile script
sl@0:     } -result {child exit}
sl@0: 
sl@0:     test Tcl_Main-5.5 {
sl@0: 	Tcl_Main: error raised in interactive mode
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {error foo} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "foo\n"
sl@0: 
sl@0:     test Tcl_Main-5.6 {
sl@0: 	Tcl_Main: interactive mode: errors don't stop command loop
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		error foo
sl@0: 		puts bar
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "foo\nbar\n"
sl@0: 
sl@0:     test Tcl_Main-5.7 {
sl@0: 	Tcl_Main: interactive mode: closed stderr
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		close stderr
sl@0: 		error foo
sl@0: 		puts bar
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "bar\n"
sl@0: 
sl@0:     test Tcl_Main-5.8 {
sl@0: 	Tcl_Main: interactive mode: close stdin
sl@0: 		-> main loop & [exit] & exit handlers
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		rename exit _exit
sl@0: 		proc exit code {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		testsetmainloop
sl@0: 		testexitmainloop
sl@0: 		testexithandler create 0
sl@0: 		close stdin
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "Exit MainLoop\nIn exit\neven 0\n"
sl@0: 
sl@0:     test Tcl_Main-5.9 {
sl@0: 	Tcl_Main: interactive mode: delete interp 
sl@0: 		-> main loop & exit handlers, but no [exit]
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		rename exit _exit
sl@0: 		proc exit code {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		testsetmainloop
sl@0: 		testexitmainloop
sl@0: 		testexithandler create 0
sl@0: 		testinterpdelete {}
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "Exit MainLoop\neven 0\n"
sl@0: 
sl@0:     test Tcl_Main-5.10 {
sl@0: 	Tcl_Main: exit main loop in mid-interactive command
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -setup {
sl@0: 	catch {set f [open "|[list [interpreter]]" w+]}
sl@0: 	catch {fconfigure $f -blocking 0}
sl@0:     } -body {
sl@0: 	type $f "testsetmainloop
sl@0: 	         after 2000 testexitmainloop
sl@0: 	         puts \{1 2"
sl@0: 	after 4000
sl@0: 	type $f "3 4\}"
sl@0: 	set code1 [catch {gets $f} line1]
sl@0: 	set code2 [catch {gets $f} line2]
sl@0: 	set code3 [catch {gets $f} line3]
sl@0: 	list $code1 $line1 $code2 $line2 $code3 $line3
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0:     } -result [list 0 {Exit MainLoop} 0 {1 2} 0 {3 4}]
sl@0: 
sl@0:     test Tcl_Main-5.11 {
sl@0: 	Tcl_Main: EOF in interactive main loop
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		rename exit _exit
sl@0: 		proc exit code {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		testexithandler create 0
sl@0: 		after 0 testexitmainloop
sl@0: 		testsetmainloop
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "Exit MainLoop\nIn exit\neven 0\n"
sl@0: 
sl@0:     test Tcl_Main-5.12 {
sl@0: 	Tcl_Main: close stdin in interactive main loop
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		rename exit _exit
sl@0: 		proc exit code {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		testexithandler create 0
sl@0: 		after 100 testexitmainloop
sl@0: 		testsetmainloop
sl@0: 		close stdin
sl@0: 		puts "don't reach this"
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "Exit MainLoop\nIn exit\neven 0\n"
sl@0: 
sl@0:     # Tests Tcl_Main-6.*: interactive operations with prompts
sl@0: 
sl@0:     test Tcl_Main-6.1 {
sl@0: 	Tcl_Main: enable prompts with tcl_interactive
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {set tcl_interactive 1} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n% "
sl@0: 
sl@0:     test Tcl_Main-6.2 {
sl@0: 	Tcl_Main: prompt deletes interp
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		set tcl_prompt1 {testinterpdelete {}}
sl@0: 		set tcl_interactive 1
sl@0: 		puts "not reached"
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n"
sl@0: 
sl@0:     test Tcl_Main-6.3 {
sl@0: 	Tcl_Main: prompt closes stdin
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		set tcl_prompt1 {close stdin}
sl@0: 		set tcl_interactive 1
sl@0: 		puts "not reached"
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n"
sl@0: 
sl@0:     test Tcl_Main-6.4 {
sl@0: 	Tcl_Main: interactive output, closed stdout
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		set tcl_interactive 1
sl@0: 		close stdout
sl@0: 		set a NO
sl@0: 		puts stderr YES
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n% YES\n"
sl@0: 
sl@0:     test Tcl_Main-6.5 {
sl@0: 	Tcl_Main: interactive entry to main loop
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		set tcl_interactive 1
sl@0: 		testsetmainloop
sl@0: 		testexitmainloop} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n% % % Exit MainLoop\n"
sl@0: 
sl@0:     test Tcl_Main-6.6 {
sl@0: 	Tcl_Main: number of prompts during stdin close exit
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		set tcl_interactive 1
sl@0: 		close stdin} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n% "
sl@0: 
sl@0:     test Tcl_Main-6.7 {
sl@0: 	[unknown]: interactive auto-completion.
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		proc foo\{ x {}
sl@0: 		set ::auto_noexec xxx
sl@0: 		set tcl_interactive 1
sl@0: 		foo y} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n% % "
sl@0: 
sl@0:     # Tests Tcl_Main-7.*: exiting
sl@0: 
sl@0:     test Tcl_Main-7.1 {
sl@0: 	Tcl_Main: [exit] defined as no-op -> still have exithandlers
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		proc exit args {}
sl@0: 		testexithandler create 0
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "even 0\n"
sl@0: 
sl@0:     test Tcl_Main-7.2 {
sl@0: 	Tcl_Main: [exit] defined as no-op -> still have exithandlers
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		proc exit args {}
sl@0: 		testexithandler create 0
sl@0: 		after 0 testexitmainloop
sl@0: 		testsetmainloop
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "Exit MainLoop\neven 0\n"
sl@0: 
sl@0:     # Tests Tcl_Main-8.*: StdinProc operations
sl@0: 
sl@0:     test Tcl_Main-8.1 {
sl@0: 	StdinProc: handles non-blocking stdin
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		fconfigure stdin -blocking 0
sl@0: 		testexitmainloop
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "Exit MainLoop\n"
sl@0: 
sl@0:     test Tcl_Main-8.2 {
sl@0: 	StdinProc: handles stdin EOF
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		testexithandler create 0
sl@0: 		rename exit _exit
sl@0: 		proc exit code {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		after 100 testexitmainloop
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "Exit MainLoop\nIn exit\neven 0\n"
sl@0: 
sl@0:     test Tcl_Main-8.3 {
sl@0: 	StdinProc: handles interactive stdin EOF
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		testexithandler create 0
sl@0: 		rename exit _exit
sl@0: 		proc exit code {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		set tcl_interactive 1} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n% even 0\n"
sl@0: 
sl@0:     test Tcl_Main-8.4 {
sl@0: 	StdinProc: handles stdin close
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		rename exit _exit
sl@0: 		proc exit code {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		after 100 testexitmainloop
sl@0: 		after 0 puts 1
sl@0: 		close stdin
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\nExit MainLoop\nIn exit\n"
sl@0: 
sl@0:     test Tcl_Main-8.5 {
sl@0: 	StdinProc: handles interactive stdin close
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		set tcl_interactive 1
sl@0: 		rename exit _exit
sl@0: 		proc exit code {
sl@0: 		    puts "In exit"
sl@0: 		    _exit $code
sl@0: 		}
sl@0: 		after 100 testexitmainloop
sl@0: 		after 0 puts 1
sl@0: 		close stdin
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n% % % after#0\n% after#1\n% 1\nExit MainLoop\nIn exit\n"
sl@0: 
sl@0:     test Tcl_Main-8.6 {
sl@0: 	StdinProc: handles event loop re-entry
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		after 100 {puts 1; set delay 1}
sl@0: 		vwait delay
sl@0: 		puts 2
sl@0: 		testexitmainloop
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n2\nExit MainLoop\n"
sl@0: 
sl@0:     test Tcl_Main-8.7 {
sl@0: 	StdinProc: handling of errors
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		error foo
sl@0: 		testexitmainloop
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "foo\nExit MainLoop\n"
sl@0: 
sl@0:     test Tcl_Main-8.8 {
sl@0: 	StdinProc: handling of errors, closed stderr
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		close stderr
sl@0: 		error foo
sl@0: 		testexitmainloop
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "Exit MainLoop\n"
sl@0: 
sl@0:     test Tcl_Main-8.9 {
sl@0: 	StdinProc: interactive output
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		set tcl_interactive 1
sl@0: 		testexitmainloop} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n% % Exit MainLoop\n"
sl@0: 
sl@0:     test Tcl_Main-8.10 {
sl@0: 	StdinProc: interactive output, closed stdout
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		close stdout
sl@0: 		set tcl_interactive 1
sl@0: 		testexitmainloop
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result {}
sl@0: 
sl@0:     test Tcl_Main-8.11 {
sl@0: 	StdinProc: prompt deletes interp
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		set tcl_prompt1 {testinterpdelete {}}
sl@0: 		set tcl_interactive 1} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n"
sl@0: 
sl@0:     test Tcl_Main-8.12 {
sl@0: 	StdinProc: prompt closes stdin
sl@0:     } -constraints {
sl@0: 	exec Tcltest
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		testsetmainloop
sl@0: 		set tcl_prompt1 {close stdin}
sl@0: 		after 100 testexitmainloop
sl@0: 		set tcl_interactive 1
sl@0: 		puts "not reached"
sl@0: 	} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\nExit MainLoop\n"
sl@0: 
sl@0:     # Tests Tcl_Main-9.*: Prompt operations
sl@0: 
sl@0:     test Tcl_Main-9.1 {
sl@0: 	Prompt: custom prompt variables
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		set tcl_prompt1 {puts -nonewline stdout "one "}
sl@0: 		set tcl_prompt2 {puts -nonewline stdout "two "}
sl@0: 		set tcl_interactive 1
sl@0: 		puts {This is
sl@0: 		a test}} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\none two This is\n\t\ta test\none "
sl@0: 
sl@0:     test Tcl_Main-9.2 {
sl@0: 	Prompt: error in custom prompt variables
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		set tcl_prompt1 {error foo}
sl@0: 		set tcl_interactive 1
sl@0: 		set errorInfo} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\nfoo\n% foo\n    while executing\n\"error foo\"\n    (script\
sl@0: 	that generates prompt)\nfoo\n% "
sl@0: 
sl@0:     test Tcl_Main-9.3 {
sl@0: 	Prompt: error in custom prompt variables, closed stderr
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		set tcl_prompt1 {close stderr; error foo}
sl@0: 		set tcl_interactive 1} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\n% "
sl@0: 
sl@0:     test Tcl_Main-9.4 {
sl@0: 	Prompt: error in custom prompt variables, closed stdout
sl@0:     } -constraints {
sl@0: 	exec
sl@0:     } -body {
sl@0: 	exec [interpreter] << {
sl@0: 		set tcl_prompt1 {close stdout; error foo}
sl@0: 		set tcl_interactive 1} >& result
sl@0: 	set f [open result]
sl@0: 	read $f
sl@0:     } -cleanup {
sl@0: 	close $f
sl@0: 	file delete result
sl@0:     } -result "1\nfoo\n"
sl@0: 
sl@0:     cd [workingDirectory]
sl@0: 
sl@0:     cleanupTests
sl@0: }
sl@0: 
sl@0: namespace delete ::tcl::test::main
sl@0: return