-
Notifications
You must be signed in to change notification settings - Fork 0
/
testmain.tcl
214 lines (180 loc) · 6.35 KB
/
testmain.tcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# -*- tcl -*- Copyright (c) 2012-2024 Andreas Kupries
# # ## ### ##### ######## ############# #####################
## Test Application (Entry point into .test files)
##
## Syntax: <localprefix> <testfile> <mode> <options>
## kt::localprefix kt::testfile kt::mode kt::argv
## mode in {scan, run}
# Kettle is designed to accomodate 8.5+
package require Tcl 8.5 9
# Accomodate use of wish as test shell.
catch {wm withdraw .}
# # ## ### ##### ######## ############# #####################
## Get the kettle information before loading tcltest.
## Everything goes into the ::kt namespace to separate things from
## tcltest and others (the testsuite).
namespace eval ::kt {}
set argv [lassign $argv kt::localprefix kt::testfile kt::mode]
# Check for valgrind
set valgrind 0
set pos [lsearch -exact $argv --valgrind]
if {$pos >= 0} {
set argv [lreplace $argv $pos $pos]
set valgrind 1
}
set kt::main $argv0
set kt::argv $argv
set argv0 $kt::testfile
#puts X_k[pid]\t[join $::auto_path \nX_k[pid]\t]
# # ## ### ##### ######## ############# #####################
## Import tcltest. This will process the remaining argv elements.
## All kettle argv elements must be processed before this point.
# Force full verbosity.
lappend argv -verbose bpstenl
package require tcltest
# We can assume tcltest 2 or higher, due to our assumption of Tcl 8.5
# or higher.
# For scan mode forcibly disable execution of tests. We cannot use the
# option -skip for this as it will also prevent output for the
# matching tests, i.e. all of them, and for the scan we want to know
# the test names. Therefore we get our desired behaviour by hacking
# the tcltest internals to suit.
if {$kt::mode eq "scan"} {
proc tcltest::test {name args} {
puts "---- $name DECL"
return
}
}
# The next command enables the execution of 'tk' constrained tests, if
# Tk is present (for example when this code is run run by 'wish').
catch {
package require Tk
wm withdraw .
}
# # ## ### ##### ######## ############# #####################
## Management utilities for communication with the 'test' recipe
## support code in our caller.
if {($kt::mode eq "scan") ||
($kt::mode eq "sub")} {
# Prevent reporting in scan and sub modes.
proc kt::Note {args} {}
} else {
proc kt::Note {k v} {
puts stdout [list @@ $k $v]
flush stdout
return
}
}
proc kt::Now {} {return [clock seconds]}
if {$kt::mode eq "scan"} {
# In scan mode we must not report, even from a sub-shell.
proc kt::Report {} {}
} elseif {$kt::mode eq "sub"} {
# In a subshell the results have to be passed up the chain to the
# caller for integration. See kt::sub below.
proc kt::Report {} {
variable ::tcltest::numTests
variable ::tcltest::skippedBecause
variable ::tcltest::createdNewFiles
tcltest::makeFile \
[list tcltest::ReportedFromSlave \
$numTests(Total) $numTests(Passed) $numTests(Skipped) \
$numTests(Failed) [array get skippedBecause] \
[array get createdNewFiles]]\n \
report
return
}
}
# Place a test script into a sub-shell.
proc kt::sub {name script args} {
# Build test file
set data ""
# Import the specified context (variables by name, and assignments).
foreach v $args {
if {[regexp {^([^=]*)=(.*)$} $v -> var val]} {
append data [list set $var $val]\n
} else {
upvar 1 $v val
append data [list set $v $val]\n
}
}
# Add the user's script, and report always, even in the presence of errors.
append data "try \{\n"
append data $script
append data "\n\} finally \{\n"
# See kt::Report above.
append data kt::Report\n
append data "\}\n"
set path [tcltest::makeFile $data $name]
# Run the file like we are run (same context and arguments, except
# for mode.
set mode sub
if {$::kt::mode eq "scan"} { set mode scan }
if {$::valgrind} {
lappend cmd [auto_execok valgrind]
}
lappend cmd [info nameofexecutable] $::kt::main $::kt::localprefix \
$path $mode {*}$::kt::argv
if {$::valgrind} {
lappend cmd --valgrind
}
try {
exec 2>@ stderr >@ stdout {*}$cmd
# Integrate the child's report into this process' statistics
eval [viewFile report]
tcltest::removeFile report
} finally {
tcltest::removeFile $path
}
return
}
# Ensure a fully normalized absolute path to the test suite location.
set ::tcltest::testsDirectory \
[file dirname [file normalize $::tcltest::testsDirectory]/___]
# # ## ### ##### ######## ############# #####################
## Start reporting, the environment in which the tests are run.
puts stdout ""
kt::Note Host [info hostname]
kt::Note Platform $tcl_platform(os)-$tcl_platform(osVersion)-$tcl_platform(machine)
kt::Note TestDir $::tcltest::testsDirectory
kt::Note LocalDir $::kt::localprefix
kt::Note TestCWD [pwd]
kt::Note Shell [info nameofexecutable]
kt::Note Tcl [info patchlevel]
# Host => Platform | Identity of the Test environment.
# Shell => Tcl |
# CWD | Identity of the package under test.
if {[llength $::tcltest::skip]} {kt::Note SkipTests $::tcltest::skip}
if {[llength $::tcltest::match]} {kt::Note MatchTests $::tcltest::match}
if {[llength $::tcltest::skipFiles]} {kt::Note SkipFiles $::tcltest::skipFiles}
if {[llength $::tcltest::matchFiles]} {kt::Note MatchFiles $::tcltest::matchFiles}
# # ## ### ##### ######## ############# #####################
## Import kettle provided utility commands (kt:: namespace)
## the testsuite can use. And a try/finally for ourselves.
source [file dirname [file normalize [info script]]]/try.tcl
source [file dirname [file normalize [info script]]]/testutilities.tcl
namespace import ::tcltest::*
# # ## ### ##### ######## ############# #####################
## Run the testsuite.
# Disable the use of exit inside of tcltest::cleanupTests.
rename exit __exit
proc exit {args} {}
kt::Note Testsuite $kt::testfile
kt::Note Start [kt::Now]
if {[catch {
source $kt::testfile
} msg]} {
# Transmit stack trace in capturable format.
puts stdout "@+"
puts stdout @|[join [split $errorInfo \n] "\n@|"]
puts stdout "@-"
}
kt::Note End [kt::Now]
puts ""
#::tcltest::cleanupTests 1
# # ## ### ##### ######## ############# #####################
# FRINK: nocheck
# Use of 'exit' ensures proper termination of the test system when
# driven by a 'wish' instead of a 'tclsh'. Otherwise 'wish' would
# enter its regular event loop and no tests would complete.
__exit