1 # tcltest compatibilty/wrapper/extension
4 set testinfo
(verbose
) 0
5 set testinfo
(numpass
) 0
6 set testinfo
(stoponerror
) 0
7 set testinfo
(template
) 0
8 set testinfo
(numfail
) 0
9 set testinfo
(numskip
) 0
10 set testinfo
(numtests
) 0
11 set testinfo
(reported
) 0
12 set testinfo
(failed
) {}
14 # -verbose or $testverbose show OK/ERR of individual tests
15 if {[lsearch $argv "-verbose"] >= 0 ||
[info exists env
(testverbose
)]} {
16 incr testinfo
(verbose
)
18 # -template causes failed tests to output a template test that would succeed
19 if {[lsearch $argv "-template"] >= 0} {
20 incr testinfo
(template
)
22 # -stoponerror or $stoponerror stops on the first failed test
23 if {[lsearch $argv "-stoponerror"] >= 0 ||
[info exists env
(stoponerror
)]} {
24 incr testinfo
(stoponerror
)
27 proc needs
{type what
{packages
{}}} {
28 if {$type eq
"constraint"} {
29 if {![info exists
::tcltest::testConstraints($what)]} {
30 set ::tcltest::testConstraints($what) 0
32 if {![set ::tcltest::testConstraints($what)]} {
33 skiptest
" (constraint $what)"
38 # Does it exist already?
39 if {[info commands
$what] ne
""} {
42 if {$packages eq
""} {
43 # e.g. exec command is in exec package
47 catch {package require
$p}
49 if {[info commands
$what] ne
""} {
52 skiptest
" (command $what)"
54 if {$type eq
"package"} {
55 if {[catch {package require
$what}]} {
56 skiptest
" (package $what)"
60 error "Unknown needs type: $type"
63 # Simplify setting constraints for whether commands exist
64 proc testCmdConstraints
{args
} {
66 testConstraint
$cmd [expr {[info commands
$cmd] ne
{}}]
70 proc skiptest
{{msg
{}}} {
71 puts [format "%16s: --- skipped$msg" $::argv0]
75 # If tcl, just use tcltest
76 if {[catch {info version
}]} {
77 package require
Tcl 8.5
78 package require
tcltest 2.1
79 namespace import
tcltest::*
81 if {$testinfo(verbose
)} {
82 configure
-verbose bps
87 ::tcltest::cleanupTests
92 # Add some search paths for packages
94 # The directory containing the original script
95 lappend auto_path
[file dirname
$argv0]
97 # The directory containing the jimsh executable
98 lappend auto_path
[file dirname
[info nameofexecutable
]]
100 # For Jim, this is reasonable compatible tcltest
101 proc makeFile
{contents name
{dir
{}}} {
105 set filename $dir/$name
107 set f
[open $filename w
]
113 proc makeDirectory
{name
} {
118 proc temporaryDirectory
{} {{dir
{}}} {
120 set dir
[file join [env TMPDIR
/tmp
] [format "tcltmp-%04x" [rand
65536]]]
126 proc removeFile
{args
} {
127 file delete
-force {*}$args
130 proc removeDirectory
{name
} {
131 file delete
-force $name
134 # In case tclcompat is not selected
135 if {![exists
-proc puts]} {
136 proc puts {{-nonewline {}} {chan stdout
} msg
} {
137 if {${-nonewline} ni
{-nonewline {}}} {
138 ${-nonewline} puts $msg
140 $chan puts {*}${-nonewline} $msg
143 proc close {chan args
} {
146 proc fileevent {args
} {
151 proc script_source
{script
} {
152 lassign
[info source $script] f l
159 proc error_source
{} {
160 lassign
[info stacktrace
] p f l
167 proc package-or-skip
{name
} {
169 package require
$name
171 puts [format "%16s: --- skipped" $::argv0]
176 proc testConstraint
{constraint
{bool
{}}} {
178 if {[info exists
::tcltest::testConstraints($constraint)]} {
179 return $::tcltest::testConstraints($constraint)
181 return -code error "unknown constraint: $constraint"
184 set ::tcltest::testConstraints($constraint) $bool
188 testConstraint
{utf8
} [expr {[string length
"\xc2\xb5"] == 1}]
189 testConstraint
{references
} [expr {[info commands getref
] ne
""}]
190 testConstraint
{jim
} 1
191 testConstraint
{tcl
} 0
193 proc bytestring
{x
} {
197 # Note: We don't support -output or -errorOutput yet
198 proc test
{id descr args
} {
199 set default [dict create
-returnCodes {ok
return} -match exact
-result {} -constraints {} -body {} -setup {} -cleanup {}]
201 if {[lindex $args 0] ni
[dict keys
$a]} {
202 if {[llength $args] == 2} {
203 lassign
$args body result constraints
204 } elseif
{[llength $args] == 3} {
205 lassign
$args constraints body result
207 return -code error "$id: Wrong syntax for tcltest::test v1"
209 tailcall test
$id $descr -body $body -result $result -constraints $constraints
211 # tcltest::test v2 syntax
214 incr ::testinfo(numtests
)
215 if {$::testinfo(verbose
)} {
216 puts -nonewline "$id "
219 foreach c
$a(-constraints) {
220 if {![testConstraint
$c]} {
221 incr ::testinfo(numskip
)
222 if {$::testinfo(verbose
)} {
229 if {[catch {uplevel 1 $a(-setup)} msg
]} {
230 if {$::testinfo(verbose
)} {
231 puts "-setup failed: $msg"
234 set rc
[catch {uplevel 1 $a(-body)} result opts
]
235 if {[catch {uplevel 1 $a(-cleanup)} msg
]} {
236 if {$::testinfo(verbose
)} {
237 puts "-cleanup failed: $msg"
241 if {[info return $rc] ni
$a(-returnCodes) && $rc ni
$a(-returnCodes)} {
243 set expected
"rc=[list $a(-returnCodes)] result=[list $a(-result)]"
244 set actual
"rc=[info return $rc] result=[list $result]"
245 # Now for the template, update -returnCodes
246 set a
(-returnCodes) [info return $rc]
248 if {$a(-match) eq
"exact"} {
249 set ok
[string equal
$a(-result) $result]
250 } elseif
{$a(-match) eq
"glob"} {
251 set ok
[string match
$a(-result) $result]
252 } elseif
{$a(-match) eq
"regexp"} {
253 set ok
[regexp $a(-result) $result]
255 return -code error "$id: unknown match type: $a(-match)"
257 set actual
[list $result]
258 set expected
[list $a(-result)]
262 if {$::testinfo(verbose
)} {
265 incr ::testinfo(numpass
)
269 if {!$::testinfo(verbose
)} {
270 puts -nonewline "$id "
274 set source [script_source
$a(-body)]
276 set source [error_source
]
278 puts "Expected: $expected"
281 if {$::testinfo(template
)} {
282 # We can't really do -match glob|regexp so
283 # just store the result as-is for -match exact
284 set a
(-result) $result
286 set template
[list test
$id $descr]
287 foreach key
{-constraints -setup -body -returnCodes -match -result -cleanup} {
288 if {$a($key) ne
$default($key)} {
289 lappend template
$key $a($key)
295 incr ::testinfo(numfail
)
296 lappend ::testinfo(failed
) [list $id $descr $source $expected $result]
297 if {$::testinfo(stoponerror
)} {
302 proc ::tcltest::cleanupTests {} {
303 file delete
[temporaryDirectory
]
308 if {$::testinfo(reported
)} {
311 incr ::testinfo(reported
)
313 if {$::testinfo(verbose
)} {
314 puts -nonewline "\n$::argv0"
316 puts -nonewline [format "%16s" $::argv0]
318 puts [format ": Total %5d Passed %5d Skipped %5d Failed %5d" \
319 $::testinfo(numtests
) $::testinfo(numpass
) $::testinfo(numskip
) $::testinfo(numfail
)]
320 if {$::testinfo(numfail
)} {
321 puts [string repeat
- 60]
322 puts "FAILED: $::testinfo(numfail)"
323 foreach failed
$::testinfo(failed
) {
324 foreach {id descr
source expected result
} $failed {}
327 puts [string repeat
- 60]
329 if {$::testinfo(numfail
)} {
335 error "deliberate error"
338 if {$testinfo(verbose
)} {
339 puts "==== $argv0 ===="