sl@0
|
1 |
# Commands covered: (test)thread
|
sl@0
|
2 |
#
|
sl@0
|
3 |
# This file contains a collection of tests for one or more of the Tcl
|
sl@0
|
4 |
# built-in commands. Sourcing this file into Tcl runs the tests and
|
sl@0
|
5 |
# generates output for errors. No output means no errors were found.
|
sl@0
|
6 |
#
|
sl@0
|
7 |
# Copyright (c) 1996 Sun Microsystems, Inc.
|
sl@0
|
8 |
# Copyright (c) 1998-1999 by Scriptics Corporation.
|
sl@0
|
9 |
#
|
sl@0
|
10 |
# See the file "license.terms" for information on usage and redistribution
|
sl@0
|
11 |
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
sl@0
|
12 |
#
|
sl@0
|
13 |
# RCS: @(#) $Id: thread.test,v 1.10 2000/05/02 22:02:36 kupries Exp $
|
sl@0
|
14 |
|
sl@0
|
15 |
if {[lsearch [namespace children] ::tcltest] == -1} {
|
sl@0
|
16 |
package require tcltest
|
sl@0
|
17 |
namespace import -force ::tcltest::*
|
sl@0
|
18 |
}
|
sl@0
|
19 |
|
sl@0
|
20 |
# Some tests require the testthread command
|
sl@0
|
21 |
|
sl@0
|
22 |
set ::tcltest::testConstraints(testthread) \
|
sl@0
|
23 |
[expr {[info commands testthread] != {}}]
|
sl@0
|
24 |
|
sl@0
|
25 |
if {$::tcltest::testConstraints(testthread)} {
|
sl@0
|
26 |
|
sl@0
|
27 |
testthread errorproc ThreadError
|
sl@0
|
28 |
|
sl@0
|
29 |
proc ThreadError {id info} {
|
sl@0
|
30 |
global threadError
|
sl@0
|
31 |
set threadError $info
|
sl@0
|
32 |
}
|
sl@0
|
33 |
|
sl@0
|
34 |
proc ThreadNullError {id info} {
|
sl@0
|
35 |
# ignore
|
sl@0
|
36 |
}
|
sl@0
|
37 |
}
|
sl@0
|
38 |
|
sl@0
|
39 |
|
sl@0
|
40 |
test thread-1.1 {Tcl_ThreadObjCmd: no args} {testthread} {
|
sl@0
|
41 |
list [catch {testthread} msg] $msg
|
sl@0
|
42 |
} {1 {wrong # args: should be "testthread option ?args?"}}
|
sl@0
|
43 |
|
sl@0
|
44 |
test thread-1.2 {Tcl_ThreadObjCmd: bad option} {testthread} {
|
sl@0
|
45 |
list [catch {testthread foo} msg] $msg
|
sl@0
|
46 |
} {1 {bad option "foo": must be create, exit, id, join, names, send, wait, or errorproc}}
|
sl@0
|
47 |
|
sl@0
|
48 |
test thread-1.3 {Tcl_ThreadObjCmd: initial thread list} {testthread} {
|
sl@0
|
49 |
list [threadReap] [llength [testthread names]]
|
sl@0
|
50 |
} {1 1}
|
sl@0
|
51 |
|
sl@0
|
52 |
test thread-1.4 {Tcl_ThreadObjCmd: thread create } {testthread} {
|
sl@0
|
53 |
threadReap
|
sl@0
|
54 |
set serverthread [testthread create]
|
sl@0
|
55 |
update
|
sl@0
|
56 |
set numthreads [llength [testthread names]]
|
sl@0
|
57 |
threadReap
|
sl@0
|
58 |
set numthreads
|
sl@0
|
59 |
} {2}
|
sl@0
|
60 |
|
sl@0
|
61 |
test thread-1.5 {Tcl_ThreadObjCmd: thread create one shot} {testthread} {
|
sl@0
|
62 |
threadReap
|
sl@0
|
63 |
testthread create {set x 5}
|
sl@0
|
64 |
foreach try {0 1 2 4 5 6} {
|
sl@0
|
65 |
# Try various ways to yield
|
sl@0
|
66 |
update
|
sl@0
|
67 |
after 10
|
sl@0
|
68 |
set l [llength [testthread names]]
|
sl@0
|
69 |
if {$l == 1} {
|
sl@0
|
70 |
break
|
sl@0
|
71 |
}
|
sl@0
|
72 |
}
|
sl@0
|
73 |
threadReap
|
sl@0
|
74 |
set l
|
sl@0
|
75 |
} {1}
|
sl@0
|
76 |
|
sl@0
|
77 |
test thread-1.6 {Tcl_ThreadObjCmd: thread exit} {testthread} {
|
sl@0
|
78 |
threadReap
|
sl@0
|
79 |
testthread create {testthread exit}
|
sl@0
|
80 |
update
|
sl@0
|
81 |
after 10
|
sl@0
|
82 |
set result [llength [testthread names]]
|
sl@0
|
83 |
threadReap
|
sl@0
|
84 |
set result
|
sl@0
|
85 |
} {1}
|
sl@0
|
86 |
|
sl@0
|
87 |
test thread-1.7 {Tcl_ThreadObjCmd: thread id args} {testthread} {
|
sl@0
|
88 |
set x [catch {testthread id x} msg]
|
sl@0
|
89 |
list $x $msg
|
sl@0
|
90 |
} {1 {wrong # args: should be "testthread id"}}
|
sl@0
|
91 |
|
sl@0
|
92 |
test thread-1.8 {Tcl_ThreadObjCmd: thread id} {testthread} {
|
sl@0
|
93 |
string compare [testthread id] $::tcltest::mainThread
|
sl@0
|
94 |
} {0}
|
sl@0
|
95 |
|
sl@0
|
96 |
test thread-1.9 {Tcl_ThreadObjCmd: thread names args} {testthread} {
|
sl@0
|
97 |
set x [catch {testthread names x} msg]
|
sl@0
|
98 |
list $x $msg
|
sl@0
|
99 |
} {1 {wrong # args: should be "testthread names"}}
|
sl@0
|
100 |
|
sl@0
|
101 |
test thread-1.10 {Tcl_ThreadObjCmd: thread id} {testthread} {
|
sl@0
|
102 |
string compare [testthread names] $::tcltest::mainThread
|
sl@0
|
103 |
} {0}
|
sl@0
|
104 |
|
sl@0
|
105 |
test thread-1.11 {Tcl_ThreadObjCmd: send args} {testthread} {
|
sl@0
|
106 |
set x [catch {testthread send} msg]
|
sl@0
|
107 |
list $x $msg
|
sl@0
|
108 |
} {1 {wrong # args: should be "testthread send ?-async? id script"}}
|
sl@0
|
109 |
|
sl@0
|
110 |
test thread-1.12 {Tcl_ThreadObjCmd: send nonint} {testthread} {
|
sl@0
|
111 |
set x [catch {testthread send abc command} msg]
|
sl@0
|
112 |
list $x $msg
|
sl@0
|
113 |
} {1 {expected integer but got "abc"}}
|
sl@0
|
114 |
|
sl@0
|
115 |
test thread-1.13 {Tcl_ThreadObjCmd: send args} {testthread} {
|
sl@0
|
116 |
threadReap
|
sl@0
|
117 |
set serverthread [testthread create]
|
sl@0
|
118 |
set five [testthread send $serverthread {set x 5}]
|
sl@0
|
119 |
threadReap
|
sl@0
|
120 |
set five
|
sl@0
|
121 |
} 5
|
sl@0
|
122 |
|
sl@0
|
123 |
test thread-1.14 {Tcl_ThreadObjCmd: send bad id} {testthread} {
|
sl@0
|
124 |
set tid [expr $::tcltest::mainThread + 10]
|
sl@0
|
125 |
set x [catch {testthread send $tid {set x 5}} msg]
|
sl@0
|
126 |
list $x $msg
|
sl@0
|
127 |
} {1 {invalid thread id}}
|
sl@0
|
128 |
|
sl@0
|
129 |
test thread-1.15 {Tcl_ThreadObjCmd: wait} {testthread} {
|
sl@0
|
130 |
threadReap
|
sl@0
|
131 |
set serverthread [testthread create {set z 5 ; testthread wait}]
|
sl@0
|
132 |
set five [testthread send $serverthread {set z}]
|
sl@0
|
133 |
threadReap
|
sl@0
|
134 |
set five
|
sl@0
|
135 |
} 5
|
sl@0
|
136 |
|
sl@0
|
137 |
test thread-1.16 {Tcl_ThreadObjCmd: errorproc args} {testthread} {
|
sl@0
|
138 |
set x [catch {testthread errorproc foo bar} msg]
|
sl@0
|
139 |
list $x $msg
|
sl@0
|
140 |
} {1 {wrong # args: should be "testthread errorproc proc"}}
|
sl@0
|
141 |
|
sl@0
|
142 |
test thread-1.17 {Tcl_ThreadObjCmd: errorproc change} {testthread} {
|
sl@0
|
143 |
testthread errorproc foo
|
sl@0
|
144 |
testthread errorproc ThreadError
|
sl@0
|
145 |
} {}
|
sl@0
|
146 |
|
sl@0
|
147 |
# The tests above also cover:
|
sl@0
|
148 |
# TclCreateThread, except when pthread_create fails
|
sl@0
|
149 |
# NewThread, safe and regular
|
sl@0
|
150 |
# ThreadErrorProc, except for printing to standard error
|
sl@0
|
151 |
|
sl@0
|
152 |
test thread-2.1 {ListUpdateInner and ListRemove} {testthread} {
|
sl@0
|
153 |
threadReap
|
sl@0
|
154 |
catch {unset tid}
|
sl@0
|
155 |
foreach t {0 1 2} {
|
sl@0
|
156 |
upvar #0 t$t tid
|
sl@0
|
157 |
set tid [testthread create]
|
sl@0
|
158 |
}
|
sl@0
|
159 |
threadReap
|
sl@0
|
160 |
} 1
|
sl@0
|
161 |
|
sl@0
|
162 |
test thread-3.1 {TclThreadList} {testthread} {
|
sl@0
|
163 |
threadReap
|
sl@0
|
164 |
catch {unset tid}
|
sl@0
|
165 |
set len [llength [testthread names]]
|
sl@0
|
166 |
set l1 {}
|
sl@0
|
167 |
foreach t {0 1 2} {
|
sl@0
|
168 |
lappend l1 [testthread create]
|
sl@0
|
169 |
}
|
sl@0
|
170 |
set l2 [testthread names]
|
sl@0
|
171 |
list $l1 $l2
|
sl@0
|
172 |
set c [string compare \
|
sl@0
|
173 |
[lsort -integer [concat $::tcltest::mainThread $l1]] \
|
sl@0
|
174 |
[lsort -integer $l2]]
|
sl@0
|
175 |
threadReap
|
sl@0
|
176 |
list $len $c
|
sl@0
|
177 |
} {1 0}
|
sl@0
|
178 |
|
sl@0
|
179 |
test thread-4.1 {TclThreadSend to self} {testthread} {
|
sl@0
|
180 |
catch {unset x}
|
sl@0
|
181 |
testthread send [testthread id] {
|
sl@0
|
182 |
set x 4
|
sl@0
|
183 |
}
|
sl@0
|
184 |
set x
|
sl@0
|
185 |
} {4}
|
sl@0
|
186 |
|
sl@0
|
187 |
test thread-4.2 {TclThreadSend -async} {testthread} {
|
sl@0
|
188 |
threadReap
|
sl@0
|
189 |
set len [llength [testthread names]]
|
sl@0
|
190 |
set serverthread [testthread create]
|
sl@0
|
191 |
testthread send -async $serverthread {
|
sl@0
|
192 |
after 1000
|
sl@0
|
193 |
testthread exit
|
sl@0
|
194 |
}
|
sl@0
|
195 |
set two [llength [testthread names]]
|
sl@0
|
196 |
after 1500 {set done 1}
|
sl@0
|
197 |
vwait done
|
sl@0
|
198 |
threadReap
|
sl@0
|
199 |
list $len [llength [testthread names]] $two
|
sl@0
|
200 |
} {1 1 2}
|
sl@0
|
201 |
|
sl@0
|
202 |
test thread-4.3 {TclThreadSend preserve errorInfo} {testthread} {
|
sl@0
|
203 |
threadReap
|
sl@0
|
204 |
set len [llength [testthread names]]
|
sl@0
|
205 |
set serverthread [testthread create]
|
sl@0
|
206 |
set x [catch {testthread send $serverthread {set undef}} msg]
|
sl@0
|
207 |
threadReap
|
sl@0
|
208 |
list $len $x $msg $errorInfo
|
sl@0
|
209 |
} {1 1 {can't read "undef": no such variable} {can't read "undef": no such variable
|
sl@0
|
210 |
while executing
|
sl@0
|
211 |
"set undef"
|
sl@0
|
212 |
invoked from within
|
sl@0
|
213 |
"testthread send $serverthread {set undef}"}}
|
sl@0
|
214 |
|
sl@0
|
215 |
test thread-4.4 {TclThreadSend preserve code} {testthread} {
|
sl@0
|
216 |
threadReap
|
sl@0
|
217 |
set len [llength [testthread names]]
|
sl@0
|
218 |
set serverthread [testthread create]
|
sl@0
|
219 |
set x [catch {testthread send $serverthread {break}} msg]
|
sl@0
|
220 |
threadReap
|
sl@0
|
221 |
list $len $x $msg $errorInfo
|
sl@0
|
222 |
} {1 3 {} {}}
|
sl@0
|
223 |
|
sl@0
|
224 |
test thread-4.5 {TclThreadSend preserve errorCode} {testthread} {
|
sl@0
|
225 |
threadReap
|
sl@0
|
226 |
set ::tcltest::mainThread [testthread names]
|
sl@0
|
227 |
set serverthread [testthread create]
|
sl@0
|
228 |
set x [catch {testthread send $serverthread {error ERR INFO CODE}} msg]
|
sl@0
|
229 |
threadReap
|
sl@0
|
230 |
list $x $msg $errorCode
|
sl@0
|
231 |
} {1 ERR CODE}
|
sl@0
|
232 |
|
sl@0
|
233 |
|
sl@0
|
234 |
test thread-5.0 {Joining threads} {testthread} {
|
sl@0
|
235 |
threadReap
|
sl@0
|
236 |
set serverthread [testthread create -joinable]
|
sl@0
|
237 |
testthread send -async $serverthread {after 1000 ; testthread exit}
|
sl@0
|
238 |
set res [testthread join $serverthread]
|
sl@0
|
239 |
threadReap
|
sl@0
|
240 |
set res
|
sl@0
|
241 |
} {0}
|
sl@0
|
242 |
|
sl@0
|
243 |
test thread-5.1 {Joining threads after the fact} {testthread} {
|
sl@0
|
244 |
threadReap
|
sl@0
|
245 |
set serverthread [testthread create -joinable]
|
sl@0
|
246 |
testthread send -async $serverthread {testthread exit}
|
sl@0
|
247 |
after 2000
|
sl@0
|
248 |
set res [testthread join $serverthread]
|
sl@0
|
249 |
threadReap
|
sl@0
|
250 |
set res
|
sl@0
|
251 |
} {0}
|
sl@0
|
252 |
|
sl@0
|
253 |
test thread-5.2 {Try to join a detached thread} {testthread} {
|
sl@0
|
254 |
threadReap
|
sl@0
|
255 |
set serverthread [testthread create]
|
sl@0
|
256 |
testthread send -async $serverthread {after 1000 ; testthread exit}
|
sl@0
|
257 |
catch {set res [testthread join $serverthread]} msg
|
sl@0
|
258 |
threadReap
|
sl@0
|
259 |
lrange $msg 0 2
|
sl@0
|
260 |
} {cannot join thread}
|
sl@0
|
261 |
|
sl@0
|
262 |
# cleanup
|
sl@0
|
263 |
::tcltest::cleanupTests
|
sl@0
|
264 |
return
|