blob: 2289446d2356141036ff9000b96f24339a58da4a (
plain)
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
|
# -*- tcl -*-
# Tests for the comm module.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2001 by ActiveState Tool Corp.
# All rights reserved.
#
# RCS: @(#) $Id: comm.test,v 1.14 2010/09/15 19:48:33 andreas_kupries Exp $
# -------------------------------------------------------------------------
source [file join \
[file dirname [file dirname [file join [pwd] [info script]]]] \
devtools testutilities.tcl]
testsNeedTcl 8.3 ; # snit
testsNeedTcltest 1.0
tcltest::testConstraint hastls [expr {![catch {package require tls}]}]
support {
# Using snit1 here, whatever the version of Tcl
use snit/snit.tcl snit
}
testing {
useLocal comm.tcl comm
}
# ------------------------------------------------------------------------
# First order of things is to spawn a separate tclsh into the background
# and have it execute comm too, with some general code to respond to our
# requests
useLocalFile comm.slaveboot
# ------------------------------------------------------------------------
test comm-1.0 {set remote variable} {
::comm::comm send [slave] {set foo b}
} {b}
test comm-1.1 {set remote variable, async} {
::comm::comm send -async [slave] {set fox a}
} {}
test comm-1.2 {get remote variables} {
::comm::comm send [slave] {list $foo $fox}
} {b a}
# ------------------------------------------------------------------------
set hack [interp create]
test comm-2.0 {-interp configuration} {
::comm::comm configure -interp $hack
} {}
test comm-2.1 {-interp configuration} {
::comm::comm configure -interp
} $hack
test comm-2.2 {-interp configuration} {
res!
res+ [::comm::comm configure -interp $hack] [::comm::comm configure -interp]
res+ [::comm::comm configure -interp {}] [::comm::comm configure -interp]
res?
} [list [list {} $hack] {{} {}}]
test comm-2.3 {-interp configuration} {
catch {::comm::comm configure -interp bad} msg
set msg
} {Non-interpreter to configuration option: -interp}
test comm-2.4 {-interp configuration, destruction} {
res!
res+ [interp exists $hack]
res+ [info commands FOO]
comm::comm new FOO -interp $hack
FOO destroy
res+ [interp exists $hack]
res+ [info commands FOO]
res?
} {1 {{}} 0 {{}}}
set hack [interp create]
set beta [interp create]
test comm-2.5 {-interp configuration, destruction} {
res!
res+ [interp exists $hack]
res+ [interp exists $beta]
res+ [info commands FOO]
comm::comm new FOO -interp $hack
FOO configure -interp $beta
FOO destroy
res+ [interp exists $hack]
res+ [interp exists $beta]
res+ [info commands FOO]
res?
} {1 1 {{}} 1 0 {{}}}
test comm-2.6 {-interp use for received scripts} {
set FOO [::comm::comm send [slave] {
set hack [interp create]
interp eval $hack {set fox 0}
comm::comm new FOO -interp $hack -listen 1
FOO self
}] ; # {}
comm::comm send $FOO {set fox 1}
set res [comm::comm send [slave] {
interp eval $hack {set fox}
}] ; # {}
comm::comm send [slave] {FOO destroy}
set res
} 1
test comm-2.7 {-interp use for received scripts} {
set FOO [::comm::comm send [slave] {
set hack [interp create]
interp eval $hack {set fox 0}
comm::comm new FOO -interp $hack -listen 1
FOO self
}] ; # {}
comm::comm send $FOO set fox 2
set res [comm::comm send [slave] {
interp eval $hack {set fox}
}] ; # {}
comm::comm send [slave] {FOO destroy}
set res
} 2
# ------------------------------------------------------------------------
test comm-3.0 {-events configuration} {
::comm::comm configure -events eval
} {}
test comm-3.1 {-events configuration} {
::comm::comm configure -events
} eval
test comm-3.2 {-events configuration} {
res!
res+ [::comm::comm configure -events eval] [::comm::comm configure -events]
res+ [::comm::comm configure -events {}] [::comm::comm configure -events]
res?
} {{{} eval} {{} {}}}
test comm-3.3 {-events configuration} {
catch {::comm::comm configure -events bad} msg
set msg
} {Non-event to configuration option: -events}
test comm-3.4 {-interp use for -events scripts, eval} {
set FOO [::comm::comm send [slave] {
set hack [interp create]
interp eval $hack {set fox 0 ; set wolf 0}
comm::comm new FOO -interp $hack -listen 1 -events eval
FOO hook eval {set wolf 2}
FOO self
}] ; # {}
comm::comm send $FOO {set fox 1}
set res [comm::comm send [slave] {
interp eval $hack {set wolf}
}] ; # {}
comm::comm send [slave] {FOO destroy}
set res
} 2
# ------------------------------------------------------------------------
test comm-4.0 {async generation of result on remote side} {
::comm::comm send [slave] {
proc future {} {
set f [comm::comm return_async]
after 3000 [list $f return "delayed $f"]
return ignored
}
}
::comm::comm send [slave] {future}
} {delayed ::comm::future1}
test comm-4.1 {async reception of a result via callback} {
set res {}
proc foo {args} {
array set tmp $args
unset tmp(-id)
unset tmp(-serial)
global res ; lappend res [dictsort [array get tmp]]
}
::comm::comm send -command foo [slave] {list $foo $fox}
vwait res
rename foo {}
set res
} {{-chan ::comm::comm -code 0 -errorcode {} -errorinfo {} -result {b a}}}
test comm-4.2 {async generation/reception of results in parallel} {
# Setup long running operations with async result generation.
::comm::comm send [slave] {
proc future {n x} {
set f [comm::comm return_async]
after $n [list $f return "delayed $x"]
return ignored
}
}
# Setup async receiver callback.
proc receive {args} {
global res tick tock
array set tmp $args
unset tmp(-id)
unset tmp(-serial)
unset tmp(-chan)
unset tmp(-code)
unset tmp(-errorcode)
unset tmp(-errorinfo)
lappend res [dictsort [array get tmp]]
incr tock -1
if {!$tock} {set tick .}
return
}
# Execute two requests, the second of which is returns before the first.
# The main point is that the server does process it due to first doing
# an async return.
set tick .
set tock 2
set res {}
::comm::comm send -command receive [slave] {future 5000 A}
::comm::comm send -command receive [slave] {future 2500 B}
vwait tick
rename receive {}
set res
# B returned before A, A was sent before B
} {{-result {delayed B}} {-result {delayed A}}}
test comm-4.3 {bug 2972571, handling of \\ by Word0} {
::comm::comm send [slave] {
proc foo {args} {
return nothing
}
}
::comm::comm send [slave] {foo \\}
} {nothing}
# ------------------------------------------------------------------------
test comm-5.0 {-port already in use} {
# First start a server on port 12345
set port 12345
catch {set shdl [socket -server foo $port]}
catch {::comm::comm new bar -port $port -listen 1 -local 0} msg
catch {close $shdl}
unset -nocomplain shdl port
set msg
} {couldn't open socket: address already in use}
# ------------------------------------------------------------------------
test comm-6.0 {secured communication via tls package} hastls {
# Setup secured channel in main process.
tls::init \
-keyfile [tcllibPath devtools/receiver.key] \
-certfile [tcllibPath devtools/receiver.crt] \
-cafile [tcllibPath devtools/ca.crt] \
-ssl2 1 \
-ssl3 1 \
-tls1 0 \
-require 1
comm::comm new BAR -socketcmd tls::socket -listen 1
# Setup secured channel in slave process
::comm::comm send [slave] {
package require tls
set fox dog
}
::comm::comm send [slave] \
[list \
tls::init \
-keyfile [tcllibPath devtools/transmitter.key] \
-certfile [tcllibPath devtools/transmitter.crt] \
-cafile [tcllibPath devtools/ca.crt] \
-ssl2 1 \
-ssl3 1 \
-tls1 0 \
-require 1]
set FOO [::comm::comm send [slave] {
comm::comm new FOO -socketcmd tls::socket -listen 1
FOO self
}] ; # {}
# Run command interaction over the secured channel
set res [BAR send $FOO {set fox}]
# Cleanup, remove secured endpoints
comm::comm send [slave] {FOO destroy}
BAR destroy
# Return result of the secured command
set res
} dog
# ------------------------------------------------------------------------
slavestop
testsuiteCleanup
return
|