1 # tcltest compatibilty/wrapper/extension
4 set testinfo
(verbose
) 0
5 set testinfo
(numpass
) 0
6 set testinfo
(stoponerror
) 0
7 set testinfo
(numfail
) 0
8 set testinfo
(numskip
) 0
9 set testinfo
(numtests
) 0
10 set testinfo
(reported
) 0
11 set testinfo
(failed
) {}
13 if {[lsearch $argv "-verbose"] >= 0 ||
[info exists env
(testverbose
)]} {
14 incr testinfo
(verbose
)
16 if {[lsearch $argv "-stoponerror"] >= 0 ||
[info exists env
(stoponerror
)]} {
17 incr testinfo
(stoponerror
)
20 proc needs
{type what
{packages
{}}} {
21 if {$type eq
"constraint"} {
22 if {![info exists
::tcltest::testConstraints($what)]} {
23 set ::tcltest::testConstraints($what) 0
25 if {![set ::tcltest::testConstraints($what)]} {
26 skiptest
" (constraint $what)"
31 # Does it exist already?
32 if {[info commands
$what] ne
""} {
35 if {$packages eq
""} {
36 # e.g. exec command is in exec package
40 catch {package require
$p}
42 if {[info commands
$what] ne
""} {
45 skiptest
" (command $what)"
47 if {$type eq
"package"} {
48 if {[catch {package require
$what}]} {
49 skiptest
" (package $what)"
53 error "Unknown needs type: $type"
56 proc skiptest
{{msg
{}}} {
57 puts [format "%16s: --- skipped$msg" $::argv0]
61 # If tcl, just use tcltest
62 if {[catch {info version
}]} {
63 package require
Tcl 8.5
64 package require
tcltest 2.1
65 namespace import
tcltest::*
67 if {$testinfo(verbose
)} {
68 configure
-verbose bps
73 ::tcltest::cleanupTests
78 # Add some search paths for packages
80 # The directory containing the original script
81 lappend auto_path
[file dirname
$argv0]
83 # The directory containing the jimsh executable
84 lappend auto_path
[file dirname
[info nameofexecutable
]]
86 # For Jim, this is reasonable compatible tcltest
87 proc makeFile
{contents name
{dir
{}}} {
91 set filename $dir/$name
93 set f
[open $filename w
]
99 proc makeDirectory
{name
} {
104 proc temporaryDirectory
{} {{dir
{}}} {
106 set dir
[file join [env TMPDIR
/tmp
] [format "tcltmp-%04x" [rand
65536]]]
112 proc removeFile
{args
} {
113 file delete
-force {*}$args
116 proc removeDirectory
{name
} {
117 file delete
-force $name
120 # In case tclcompat is not selected
121 if {![exists
-proc puts]} {
122 proc puts {{-nonewline {}} {chan stdout
} msg
} {
123 if {${-nonewline} ni
{-nonewline {}}} {
124 ${-nonewline} puts $msg
126 $chan puts {*}${-nonewline} $msg
129 proc close {chan args
} {
132 proc fileevent {args
} {
137 proc script_source
{script
} {
138 lassign
[info source $script] f l
145 proc error_source
{} {
146 lassign
[info stacktrace
] p f l
153 proc package-or-skip
{name
} {
155 package require
$name
157 puts [format "%16s: --- skipped" $::argv0]
162 proc testConstraint
{constraint
{bool
{}}} {
164 if {[info exists
::tcltest::testConstraints($constraint)]} {
165 return $::tcltest::testConstraints($constraint)
167 return -code error "unknown constraint: $constraint"
170 set ::tcltest::testConstraints($constraint) $bool
174 testConstraint
{utf8
} [expr {[string length
"\xc2\xb5"] == 1}]
175 testConstraint
{references
} [expr {[info commands getref
] ne
""}]
176 testConstraint
{jim
} 1
177 testConstraint
{tcl
} 0
179 proc bytestring
{x
} {
183 # Note: We don't support -output or -errorOutput yet
184 proc test
{id descr args
} {
185 set a
[dict create
-returnCodes {ok
return} -match exact
-result {} -constraints {} -body {} -setup {} -cleanup {}]
186 if {[lindex $args 0] ni
[dict keys
$a]} {
187 if {[llength $args] == 2} {
188 lassign
$args body result constraints
189 } elseif
{[llength $args] == 3} {
190 lassign
$args constraints body result
192 return -code error "$id: Wrong syntax for tcltest::test v1"
194 tailcall test
$id $descr -body $body -result $result -constraints $constraints
196 # tcltest::test v2 syntax
199 incr ::testinfo(numtests
)
200 if {$::testinfo(verbose
)} {
201 puts -nonewline "$id "
204 foreach c
$a(-constraints) {
205 if {![testConstraint
$c]} {
206 incr ::testinfo(numskip
)
207 if {$::testinfo(verbose
)} {
214 if {[catch {uplevel 1 $a(-setup)} msg
]} {
215 if {$::testinfo(verbose
)} {
216 puts "-setup failed: $msg"
219 set rc
[catch {uplevel 1 $a(-body)} result opts
]
220 if {[catch {uplevel 1 $a(-cleanup)} msg
]} {
221 if {$::testinfo(verbose
)} {
222 puts "-cleanup failed: $msg"
226 if {[info return $rc] ni
$a(-returnCodes) && $rc ni
$a(-returnCodes)} {
228 set expected
"rc=$a(-returnCodes) result=$a(-result)"
229 set result
"rc=[info return $rc] result=$result"
231 if {$a(-match) eq
"exact"} {
232 set ok
[string equal
$a(-result) $result]
233 } elseif
{$a(-match) eq
"glob"} {
234 set ok
[string match
$a(-result) $result]
235 } elseif
{$a(-match) eq
"regexp"} {
236 set ok
[regexp $a(-result) $result]
238 return -code error "$id: unknown match type: $a(-match)"
240 set expected
$a(-result)
244 if {$::testinfo(verbose
)} {
247 incr ::testinfo(numpass
)
251 if {!$::testinfo(verbose
)} {
252 puts -nonewline "$id "
256 set source [script_source
$a(-body)]
258 set source [error_source
]
260 puts "Expected: '$expected'"
261 puts "Got : '$result'"
263 incr ::testinfo(numfail
)
264 lappend ::testinfo(failed
) [list $id $descr $source $expected $result]
265 if {$::testinfo(stoponerror
)} {
270 proc ::tcltest::cleanupTests {} {
271 file delete
[temporaryDirectory
]
276 if {$::testinfo(reported
)} {
279 incr ::testinfo(reported
)
281 if {$::testinfo(verbose
)} {
282 puts -nonewline "\n$::argv0"
284 puts -nonewline [format "%16s" $::argv0]
286 puts [format ": Total %5d Passed %5d Skipped %5d Failed %5d" \
287 $::testinfo(numtests
) $::testinfo(numpass
) $::testinfo(numskip
) $::testinfo(numfail
)]
288 if {$::testinfo(numfail
)} {
289 puts [string repeat
- 60]
290 puts "FAILED: $::testinfo(numfail)"
291 foreach failed
$::testinfo(failed
) {
292 foreach {id descr
source expected result
} $failed {}
295 puts [string repeat
- 60]
297 if {$::testinfo(numfail
)} {
303 error "deliberate error"
306 if {$testinfo(verbose
)} {
307 puts "==== $argv0 ===="