1 | # -*- tcl -*- |
---|
2 | # Commands covered: transform, and stacking in general |
---|
3 | # |
---|
4 | # This file contains a collection of tests for Giot |
---|
5 | # |
---|
6 | # See the file "license.terms" for information on usage and redistribution |
---|
7 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
8 | # |
---|
9 | # Copyright (c) 2000 Ajuba Solutions. |
---|
10 | # Copyright (c) 2000 Andreas Kupries. |
---|
11 | # All rights reserved. |
---|
12 | # |
---|
13 | # RCS: @(#) $Id: iogt.test,v 1.16 2006/11/03 11:45:34 dkf Exp $ |
---|
14 | |
---|
15 | if {[catch {package require tcltest 2.1}]} { |
---|
16 | puts stderr "Skipping tests in [info script]. tcltest 2.1 required." |
---|
17 | return |
---|
18 | } |
---|
19 | namespace eval ::tcl::test::iogt { |
---|
20 | namespace import ::tcltest::* |
---|
21 | |
---|
22 | testConstraint testchannel [llength [info commands testchannel]] |
---|
23 | |
---|
24 | set path(dummy) [makeFile {abcdefghijklmnopqrstuvwxyz0123456789,./?><;'\|":[]\}\{`~!@#$%^&*()_+-= |
---|
25 | } dummy] |
---|
26 | |
---|
27 | # " capture coloring of quotes |
---|
28 | |
---|
29 | set path(dummyout) [makeFile {} dummyout] |
---|
30 | |
---|
31 | set path(__echo_srv__.tcl) [makeFile { |
---|
32 | #!/usr/local/bin/tclsh |
---|
33 | # -*- tcl -*- |
---|
34 | # echo server |
---|
35 | # |
---|
36 | # arguments, options: port to listen on for connections. |
---|
37 | # delay till echo of first block |
---|
38 | # delay between blocks |
---|
39 | # blocksize ... |
---|
40 | |
---|
41 | set port [lindex $argv 0] |
---|
42 | set fdelay [lindex $argv 1] |
---|
43 | set idelay [lindex $argv 2] |
---|
44 | set bsizes [lrange $argv 3 end] |
---|
45 | set c 0 |
---|
46 | |
---|
47 | proc newconn {sock rhost rport} { |
---|
48 | variable fdelay |
---|
49 | variable c |
---|
50 | incr c |
---|
51 | variable c$c |
---|
52 | |
---|
53 | #puts stdout "C $sock $rhost $rport / $fdelay" ; flush stdout |
---|
54 | |
---|
55 | upvar 0 c$c conn |
---|
56 | set conn(after) {} |
---|
57 | set conn(state) 0 |
---|
58 | set conn(size) 0 |
---|
59 | set conn(data) "" |
---|
60 | set conn(delay) $fdelay |
---|
61 | |
---|
62 | fileevent $sock readable [list echoGet $c $sock] |
---|
63 | fconfigure $sock -translation binary -buffering none -blocking 0 |
---|
64 | } |
---|
65 | |
---|
66 | proc echoGet {c sock} { |
---|
67 | variable fdelay |
---|
68 | variable c$c |
---|
69 | upvar 0 c$c conn |
---|
70 | |
---|
71 | if {[eof $sock]} { |
---|
72 | # one-shot echo |
---|
73 | exit |
---|
74 | } |
---|
75 | |
---|
76 | append conn(data) [read $sock] |
---|
77 | |
---|
78 | #puts stdout "G $c $sock $conn(data) <<$conn(data)>>" ; flush stdout |
---|
79 | |
---|
80 | if {$conn(after) == {}} { |
---|
81 | set conn(after) [after $conn(delay) [list echoPut $c $sock]] |
---|
82 | } |
---|
83 | } |
---|
84 | |
---|
85 | proc echoPut {c sock} { |
---|
86 | variable idelay |
---|
87 | variable fdelay |
---|
88 | variable bsizes |
---|
89 | variable c$c |
---|
90 | upvar 0 c$c conn |
---|
91 | |
---|
92 | if {[string length $conn(data)] == 0} { |
---|
93 | #puts stdout "C $c $sock" ; flush stdout |
---|
94 | # auto terminate |
---|
95 | close $sock |
---|
96 | exit |
---|
97 | #set conn(delay) $fdelay |
---|
98 | return |
---|
99 | } |
---|
100 | |
---|
101 | |
---|
102 | set conn(delay) $idelay |
---|
103 | |
---|
104 | set n [lindex $bsizes $conn(size)] |
---|
105 | |
---|
106 | #puts stdout "P $c $sock $n >>" ; flush stdout |
---|
107 | |
---|
108 | #puts __________________________________________ |
---|
109 | #parray conn |
---|
110 | #puts n=<$n> |
---|
111 | |
---|
112 | |
---|
113 | if {[string length $conn(data)] >= $n} { |
---|
114 | puts -nonewline $sock [string range $conn(data) 0 $n] |
---|
115 | set conn(data) [string range $conn(data) [incr n] end] |
---|
116 | } |
---|
117 | |
---|
118 | incr conn(size) |
---|
119 | if {$conn(size) >= [llength $bsizes]} { |
---|
120 | set conn(size) [expr {[llength $bsizes]-1}] |
---|
121 | } |
---|
122 | |
---|
123 | set conn(after) [after $conn(delay) [list echoPut $c $sock]] |
---|
124 | } |
---|
125 | |
---|
126 | #fileevent stdin readable {exit ;#cut} |
---|
127 | |
---|
128 | # main |
---|
129 | socket -server newconn -myaddr 127.0.0.1 $port |
---|
130 | vwait forever |
---|
131 | } __echo_srv__.tcl] |
---|
132 | |
---|
133 | |
---|
134 | ######################################################################## |
---|
135 | |
---|
136 | proc fevent {fdelay idelay blocks script data} { |
---|
137 | # start and initialize an echo server, prepare data |
---|
138 | # transmission, then hand over to the test script. |
---|
139 | # this has to start real transmission via 'flush'. |
---|
140 | # The server is stopped after completion of the test. |
---|
141 | |
---|
142 | # fixed port, not so good. lets hope for the best, for now. |
---|
143 | set port 4000 |
---|
144 | |
---|
145 | exec tclsh __echo_srv__.tcl \ |
---|
146 | $port $fdelay $idelay {*}$blocks >@stdout & |
---|
147 | |
---|
148 | after 500 |
---|
149 | |
---|
150 | #puts stdout "> $port" ; flush stdout |
---|
151 | |
---|
152 | set sk [socket localhost $port] |
---|
153 | fconfigure $sk \ |
---|
154 | -blocking 0 \ |
---|
155 | -buffering full \ |
---|
156 | -buffersize [expr {10+[llength $data]}] |
---|
157 | |
---|
158 | puts -nonewline $sk $data |
---|
159 | |
---|
160 | # The channel is prepared to go off. |
---|
161 | |
---|
162 | #puts stdout ">>>>>" ; flush stdout |
---|
163 | |
---|
164 | uplevel #0 set sock $sk |
---|
165 | set res [uplevel #0 $script] |
---|
166 | |
---|
167 | catch {close $sk} |
---|
168 | return $res |
---|
169 | } |
---|
170 | |
---|
171 | # -------------------------------------------------------------- |
---|
172 | # utility transformations ... |
---|
173 | |
---|
174 | proc id {op data} { |
---|
175 | switch -- $op { |
---|
176 | create/write - |
---|
177 | create/read - |
---|
178 | delete/write - |
---|
179 | delete/read - |
---|
180 | clear_read {;#ignore} |
---|
181 | flush/write - |
---|
182 | flush/read - |
---|
183 | write - |
---|
184 | read { |
---|
185 | return $data |
---|
186 | } |
---|
187 | query/maxRead {return -1} |
---|
188 | } |
---|
189 | } |
---|
190 | |
---|
191 | proc id_optrail {var op data} { |
---|
192 | variable $var |
---|
193 | upvar 0 $var trail |
---|
194 | |
---|
195 | lappend trail $op |
---|
196 | |
---|
197 | switch -- $op { |
---|
198 | create/write - create/read - |
---|
199 | delete/write - delete/read - |
---|
200 | flush/read - |
---|
201 | clear/read { #ignore } |
---|
202 | flush/write - |
---|
203 | write - |
---|
204 | read { |
---|
205 | return $data |
---|
206 | } |
---|
207 | query/maxRead { |
---|
208 | return -1 |
---|
209 | } |
---|
210 | default { |
---|
211 | lappend trail "error $op" |
---|
212 | error $op |
---|
213 | } |
---|
214 | } |
---|
215 | } |
---|
216 | |
---|
217 | |
---|
218 | proc id_fulltrail {var op data} { |
---|
219 | variable $var |
---|
220 | upvar 0 $var trail |
---|
221 | |
---|
222 | #puts stdout ">> $var $op $data" ; flush stdout |
---|
223 | |
---|
224 | switch -- $op { |
---|
225 | create/write - create/read - |
---|
226 | delete/write - delete/read - |
---|
227 | clear_read { |
---|
228 | set res *ignored* |
---|
229 | } |
---|
230 | flush/write - flush/read - |
---|
231 | write - |
---|
232 | read { |
---|
233 | set res $data |
---|
234 | } |
---|
235 | query/maxRead { |
---|
236 | set res -1 |
---|
237 | } |
---|
238 | } |
---|
239 | |
---|
240 | #catch {puts stdout "\t>* $res" ; flush stdout} |
---|
241 | #catch {puts stdout "x$res"} msg |
---|
242 | |
---|
243 | lappend trail [list $op $data $res] |
---|
244 | return $res |
---|
245 | } |
---|
246 | |
---|
247 | proc counter {var op data} { |
---|
248 | variable $var |
---|
249 | upvar 0 $var n |
---|
250 | |
---|
251 | switch -- $op { |
---|
252 | create/write - create/read - |
---|
253 | delete/write - delete/read - |
---|
254 | clear_read {;#ignore} |
---|
255 | flush/write - flush/read {return {}} |
---|
256 | write { |
---|
257 | return $data |
---|
258 | } |
---|
259 | read { |
---|
260 | if {$n > 0} { |
---|
261 | incr n -[string length $data] |
---|
262 | if {$n < 0} { |
---|
263 | set n 0 |
---|
264 | } |
---|
265 | } |
---|
266 | return $data |
---|
267 | } |
---|
268 | query/maxRead { |
---|
269 | return $n |
---|
270 | } |
---|
271 | } |
---|
272 | } |
---|
273 | |
---|
274 | |
---|
275 | proc counter_audit {var vtrail op data} { |
---|
276 | variable $var |
---|
277 | variable $vtrail |
---|
278 | upvar 0 $var n $vtrail trail |
---|
279 | |
---|
280 | switch -- $op { |
---|
281 | create/write - create/read - |
---|
282 | delete/write - delete/read - |
---|
283 | clear_read { |
---|
284 | set res {} |
---|
285 | } |
---|
286 | flush/write - flush/read { |
---|
287 | set res {} |
---|
288 | } |
---|
289 | write { |
---|
290 | set res $data |
---|
291 | } |
---|
292 | read { |
---|
293 | if {$n > 0} { |
---|
294 | incr n -[string length $data] |
---|
295 | if {$n < 0} { |
---|
296 | set n 0 |
---|
297 | } |
---|
298 | } |
---|
299 | set res $data |
---|
300 | } |
---|
301 | query/maxRead { |
---|
302 | set res $n |
---|
303 | } |
---|
304 | } |
---|
305 | |
---|
306 | lappend trail [list counter:$op $data $res] |
---|
307 | return $res |
---|
308 | } |
---|
309 | |
---|
310 | |
---|
311 | proc rblocks {var vtrail n op data} { |
---|
312 | variable $var |
---|
313 | variable $vtrail |
---|
314 | upvar 0 $var buf $vtrail trail |
---|
315 | |
---|
316 | set res {} |
---|
317 | |
---|
318 | switch -- $op { |
---|
319 | create/write - create/read - |
---|
320 | delete/write - delete/read - |
---|
321 | clear_read { |
---|
322 | set buf {} |
---|
323 | } |
---|
324 | flush/write { |
---|
325 | } |
---|
326 | flush/read { |
---|
327 | set res $buf |
---|
328 | set buf {} |
---|
329 | } |
---|
330 | write { |
---|
331 | set data |
---|
332 | } |
---|
333 | read { |
---|
334 | append buf $data |
---|
335 | |
---|
336 | set b [expr {$n * ([string length $buf] / $n)}] |
---|
337 | |
---|
338 | append op " $n [string length $buf] :- $b" |
---|
339 | |
---|
340 | set res [string range $buf 0 [incr b -1]] |
---|
341 | set buf [string range $buf [incr b] end] |
---|
342 | #return $res |
---|
343 | } |
---|
344 | query/maxRead { |
---|
345 | set res -1 |
---|
346 | } |
---|
347 | } |
---|
348 | |
---|
349 | lappend trail [list rblock | $op $data $res | $buf] |
---|
350 | return $res |
---|
351 | } |
---|
352 | |
---|
353 | |
---|
354 | # -------------------------------------------------------------- |
---|
355 | # ... and convenience procedures to stack them |
---|
356 | |
---|
357 | proc identity {-attach channel} { |
---|
358 | testchannel transform $channel -command [namespace code id] |
---|
359 | } |
---|
360 | |
---|
361 | proc audit_ops {var -attach channel} { |
---|
362 | testchannel transform $channel -command [namespace code [list id_optrail $var]] |
---|
363 | } |
---|
364 | |
---|
365 | proc audit_flow {var -attach channel} { |
---|
366 | testchannel transform $channel -command [namespace code [list id_fulltrail $var]] |
---|
367 | } |
---|
368 | |
---|
369 | proc stopafter {var n -attach channel} { |
---|
370 | variable $var |
---|
371 | upvar 0 $var vn |
---|
372 | set vn $n |
---|
373 | testchannel transform $channel -command [namespace code [list counter $var]] |
---|
374 | } |
---|
375 | |
---|
376 | proc stopafter_audit {var trail n -attach channel} { |
---|
377 | variable $var |
---|
378 | upvar 0 $var vn |
---|
379 | set vn $n |
---|
380 | testchannel transform $channel -command [namespace code [list counter_audit $var $trail]] |
---|
381 | } |
---|
382 | |
---|
383 | proc rblocks_t {var trail n -attach channel} { |
---|
384 | testchannel transform $channel -command [namespace code [list rblocks $var $trail $n]] |
---|
385 | } |
---|
386 | |
---|
387 | # -------------------------------------------------------------- |
---|
388 | # serialize an array, with keys in sorted order. |
---|
389 | |
---|
390 | proc array_sget {v} { |
---|
391 | upvar $v a |
---|
392 | |
---|
393 | set res [list] |
---|
394 | foreach n [lsort [array names a]] { |
---|
395 | lappend res $n $a($n) |
---|
396 | } |
---|
397 | set res |
---|
398 | } |
---|
399 | |
---|
400 | proc asort {alist} { |
---|
401 | # sort a list of key/value pairs by key, removes duplicates too. |
---|
402 | |
---|
403 | array set a $alist |
---|
404 | array_sget a |
---|
405 | } |
---|
406 | |
---|
407 | ######################################################################## |
---|
408 | |
---|
409 | test iogt-1.1 {stack/unstack} testchannel { |
---|
410 | set fh [open $path(dummy) r] |
---|
411 | identity -attach $fh |
---|
412 | testchannel unstack $fh |
---|
413 | close $fh |
---|
414 | } {} |
---|
415 | |
---|
416 | test iogt-1.2 {stack/close} testchannel { |
---|
417 | set fh [open $path(dummy) r] |
---|
418 | identity -attach $fh |
---|
419 | close $fh |
---|
420 | } {} |
---|
421 | |
---|
422 | test iogt-1.3 {stack/unstack, configuration, options} testchannel { |
---|
423 | set fh [open $path(dummy) r] |
---|
424 | set ca [asort [fconfigure $fh]] |
---|
425 | identity -attach $fh |
---|
426 | set cb [asort [fconfigure $fh]] |
---|
427 | testchannel unstack $fh |
---|
428 | set cc [asort [fconfigure $fh]] |
---|
429 | close $fh |
---|
430 | |
---|
431 | # With this system none of the buffering, translation and |
---|
432 | # encoding option may change their values with channels |
---|
433 | # stacked upon each other or not. |
---|
434 | |
---|
435 | # cb == ca == cc |
---|
436 | |
---|
437 | list [string equal $ca $cb] [string equal $cb $cc] [string equal $ca $cc] |
---|
438 | } {1 1 1} |
---|
439 | |
---|
440 | test iogt-1.4 {stack/unstack, configuration} testchannel { |
---|
441 | set fh [open $path(dummy) r] |
---|
442 | set ca [asort [fconfigure $fh]] |
---|
443 | identity -attach $fh |
---|
444 | fconfigure $fh \ |
---|
445 | -buffering line \ |
---|
446 | -translation cr \ |
---|
447 | -encoding shiftjis |
---|
448 | testchannel unstack $fh |
---|
449 | set cc [asort [fconfigure $fh]] |
---|
450 | |
---|
451 | set res [list \ |
---|
452 | [string equal $ca $cc] \ |
---|
453 | [fconfigure $fh -buffering] \ |
---|
454 | [fconfigure $fh -translation] \ |
---|
455 | [fconfigure $fh -encoding] \ |
---|
456 | ] |
---|
457 | |
---|
458 | close $fh |
---|
459 | set res |
---|
460 | } {0 line cr shiftjis} |
---|
461 | |
---|
462 | test iogt-2.0 {basic I/O going through transform} testchannel { |
---|
463 | set fin [open $path(dummy) r] |
---|
464 | set fout [open $path(dummyout) w] |
---|
465 | |
---|
466 | identity -attach $fin |
---|
467 | identity -attach $fout |
---|
468 | |
---|
469 | fcopy $fin $fout |
---|
470 | |
---|
471 | close $fin |
---|
472 | close $fout |
---|
473 | |
---|
474 | set fin [open $path(dummy) r] |
---|
475 | set fout [open $path(dummyout) r] |
---|
476 | |
---|
477 | set res [string equal [set in [read $fin]] [set out [read $fout]]] |
---|
478 | lappend res [string length $in] [string length $out] |
---|
479 | |
---|
480 | close $fin |
---|
481 | close $fout |
---|
482 | |
---|
483 | set res |
---|
484 | } {1 71 71} |
---|
485 | |
---|
486 | |
---|
487 | test iogt-2.1 {basic I/O, operation trail} {testchannel unix} { |
---|
488 | set fin [open $path(dummy) r] |
---|
489 | set fout [open $path(dummyout) w] |
---|
490 | |
---|
491 | set ain [list] ; set aout [list] |
---|
492 | audit_ops ain -attach $fin |
---|
493 | audit_ops aout -attach $fout |
---|
494 | |
---|
495 | fconfigure $fin -buffersize 10 |
---|
496 | fconfigure $fout -buffersize 10 |
---|
497 | |
---|
498 | fcopy $fin $fout |
---|
499 | |
---|
500 | close $fin |
---|
501 | close $fout |
---|
502 | |
---|
503 | set res "[join $ain \n]\n--------\n[join $aout \n]" |
---|
504 | } {create/read |
---|
505 | query/maxRead |
---|
506 | read |
---|
507 | query/maxRead |
---|
508 | read |
---|
509 | query/maxRead |
---|
510 | read |
---|
511 | query/maxRead |
---|
512 | read |
---|
513 | query/maxRead |
---|
514 | read |
---|
515 | query/maxRead |
---|
516 | read |
---|
517 | query/maxRead |
---|
518 | read |
---|
519 | query/maxRead |
---|
520 | read |
---|
521 | query/maxRead |
---|
522 | flush/read |
---|
523 | delete/read |
---|
524 | -------- |
---|
525 | create/write |
---|
526 | write |
---|
527 | write |
---|
528 | write |
---|
529 | write |
---|
530 | write |
---|
531 | write |
---|
532 | write |
---|
533 | write |
---|
534 | flush/write |
---|
535 | delete/write} |
---|
536 | |
---|
537 | test iogt-2.2 {basic I/O, data trail} {testchannel unix} { |
---|
538 | set fin [open $path(dummy) r] |
---|
539 | set fout [open $path(dummyout) w] |
---|
540 | |
---|
541 | set ain [list] ; set aout [list] |
---|
542 | audit_flow ain -attach $fin |
---|
543 | audit_flow aout -attach $fout |
---|
544 | |
---|
545 | fconfigure $fin -buffersize 10 |
---|
546 | fconfigure $fout -buffersize 10 |
---|
547 | |
---|
548 | fcopy $fin $fout |
---|
549 | |
---|
550 | close $fin |
---|
551 | close $fout |
---|
552 | |
---|
553 | set res "[join $ain \n]\n--------\n[join $aout \n]" |
---|
554 | } {create/read {} *ignored* |
---|
555 | query/maxRead {} -1 |
---|
556 | read abcdefghij abcdefghij |
---|
557 | query/maxRead {} -1 |
---|
558 | read klmnopqrst klmnopqrst |
---|
559 | query/maxRead {} -1 |
---|
560 | read uvwxyz0123 uvwxyz0123 |
---|
561 | query/maxRead {} -1 |
---|
562 | read 456789,./? 456789,./? |
---|
563 | query/maxRead {} -1 |
---|
564 | read {><;'\|":[]} {><;'\|":[]} |
---|
565 | query/maxRead {} -1 |
---|
566 | read {\}\{`~!@#$} {\}\{`~!@#$} |
---|
567 | query/maxRead {} -1 |
---|
568 | read %^&*()_+-= %^&*()_+-= |
---|
569 | query/maxRead {} -1 |
---|
570 | read { |
---|
571 | } { |
---|
572 | } |
---|
573 | query/maxRead {} -1 |
---|
574 | flush/read {} {} |
---|
575 | delete/read {} *ignored* |
---|
576 | -------- |
---|
577 | create/write {} *ignored* |
---|
578 | write abcdefghij abcdefghij |
---|
579 | write klmnopqrst klmnopqrst |
---|
580 | write uvwxyz0123 uvwxyz0123 |
---|
581 | write 456789,./? 456789,./? |
---|
582 | write {><;'\|":[]} {><;'\|":[]} |
---|
583 | write {\}\{`~!@#$} {\}\{`~!@#$} |
---|
584 | write %^&*()_+-= %^&*()_+-= |
---|
585 | write { |
---|
586 | } { |
---|
587 | } |
---|
588 | flush/write {} {} |
---|
589 | delete/write {} *ignored*} |
---|
590 | |
---|
591 | |
---|
592 | test iogt-2.3 {basic I/O, mixed trail} {testchannel unix} { |
---|
593 | set fin [open $path(dummy) r] |
---|
594 | set fout [open $path(dummyout) w] |
---|
595 | |
---|
596 | set trail [list] |
---|
597 | audit_flow trail -attach $fin |
---|
598 | audit_flow trail -attach $fout |
---|
599 | |
---|
600 | fconfigure $fin -buffersize 20 |
---|
601 | fconfigure $fout -buffersize 10 |
---|
602 | |
---|
603 | fcopy $fin $fout |
---|
604 | |
---|
605 | close $fin |
---|
606 | close $fout |
---|
607 | |
---|
608 | join $trail \n |
---|
609 | } {create/read {} *ignored* |
---|
610 | create/write {} *ignored* |
---|
611 | query/maxRead {} -1 |
---|
612 | read abcdefghijklmnopqrst abcdefghijklmnopqrst |
---|
613 | write abcdefghij abcdefghij |
---|
614 | write klmnopqrst klmnopqrst |
---|
615 | query/maxRead {} -1 |
---|
616 | read uvwxyz0123456789,./? uvwxyz0123456789,./? |
---|
617 | write uvwxyz0123 uvwxyz0123 |
---|
618 | write 456789,./? 456789,./? |
---|
619 | query/maxRead {} -1 |
---|
620 | read {><;'\|":[]\}\{`~!@#$} {><;'\|":[]\}\{`~!@#$} |
---|
621 | write {><;'\|":[]} {><;'\|":[]} |
---|
622 | write {\}\{`~!@#$} {\}\{`~!@#$} |
---|
623 | query/maxRead {} -1 |
---|
624 | read {%^&*()_+-= |
---|
625 | } {%^&*()_+-= |
---|
626 | } |
---|
627 | query/maxRead {} -1 |
---|
628 | flush/read {} {} |
---|
629 | write %^&*()_+-= %^&*()_+-= |
---|
630 | write { |
---|
631 | } { |
---|
632 | } |
---|
633 | delete/read {} *ignored* |
---|
634 | flush/write {} {} |
---|
635 | delete/write {} *ignored*} |
---|
636 | |
---|
637 | |
---|
638 | test iogt-3.0 {Tcl_Channel valid after stack/unstack, fevent handling} \ |
---|
639 | {testchannel unknownFailure} { |
---|
640 | # This test to check the validity of aquired Tcl_Channel references is |
---|
641 | # not possible because even a backgrounded fcopy will immediately start |
---|
642 | # to copy data, without waiting for the event loop. This is done only in |
---|
643 | # case of an underflow on the read size!. So stacking transforms after the |
---|
644 | # fcopy will miss information, or are not used at all. |
---|
645 | # |
---|
646 | # I was able to circumvent this by using the echo.tcl server with a big |
---|
647 | # delay, causing the fcopy to underflow immediately. |
---|
648 | |
---|
649 | proc DoneCopy {n {err {}}} { |
---|
650 | variable copy ; set copy 1 |
---|
651 | } |
---|
652 | |
---|
653 | set fin [open $path(dummy) r] |
---|
654 | |
---|
655 | fevent 1000 500 {20 20 20 10 1 1} { |
---|
656 | close $fin |
---|
657 | |
---|
658 | set fout [open dummyout w] |
---|
659 | |
---|
660 | flush $sock ; # now, or fcopy will error us out |
---|
661 | # But the 1 second delay should be enough to |
---|
662 | # initialize everything else here. |
---|
663 | |
---|
664 | fcopy $sock $fout -command [namespace code DoneCopy] |
---|
665 | |
---|
666 | # transform after fcopy got its handles ! |
---|
667 | # They should be still valid for fcopy. |
---|
668 | |
---|
669 | set trail [list] |
---|
670 | audit_ops trail -attach $fout |
---|
671 | |
---|
672 | vwait [namespace which -variable copy] |
---|
673 | } [read $fin] ; # {} |
---|
674 | |
---|
675 | close $fout |
---|
676 | |
---|
677 | rename DoneCopy {} |
---|
678 | |
---|
679 | # Check result of copy. |
---|
680 | |
---|
681 | set fin [open $path(dummy) r] |
---|
682 | set fout [open $path(dummyout) r] |
---|
683 | |
---|
684 | set res [string equal [read $fin] [read $fout]] |
---|
685 | |
---|
686 | close $fin |
---|
687 | close $fout |
---|
688 | |
---|
689 | list $res $trail |
---|
690 | } {1 {create/write create/read write flush/write flush/read delete/write delete/read}} |
---|
691 | |
---|
692 | |
---|
693 | test iogt-4.0 {fileevent readable, after transform} {testchannel unknownFailure} { |
---|
694 | set fin [open $path(dummy) r] |
---|
695 | set data [read $fin] |
---|
696 | close $fin |
---|
697 | |
---|
698 | set trail [list] |
---|
699 | set got [list] |
---|
700 | |
---|
701 | proc Done {args} { |
---|
702 | variable stop |
---|
703 | set stop 1 |
---|
704 | } |
---|
705 | |
---|
706 | proc Get {sock} { |
---|
707 | variable trail |
---|
708 | variable got |
---|
709 | if {[eof $sock]} { |
---|
710 | Done |
---|
711 | lappend trail "xxxxxxxxxxxxx" |
---|
712 | close $sock |
---|
713 | return |
---|
714 | } |
---|
715 | lappend trail "vvvvvvvvvvvvv" |
---|
716 | lappend trail "\tgot: [lappend got "\[\[[read $sock]\]\]"]" |
---|
717 | lappend trail "=============" |
---|
718 | #puts stdout $__ ; flush stdout |
---|
719 | #read $sock |
---|
720 | } |
---|
721 | |
---|
722 | fevent 1000 500 {20 20 20 10 1} { |
---|
723 | audit_flow trail -attach $sock |
---|
724 | rblocks_t rbuf trail 23 -attach $sock |
---|
725 | |
---|
726 | fileevent $sock readable [list Get $sock] |
---|
727 | |
---|
728 | flush $sock ; # now, or fcopy will error us out |
---|
729 | # But the 1 second delay should be enough to |
---|
730 | # initialize everything else here. |
---|
731 | |
---|
732 | vwait [namespace which -variable stop] |
---|
733 | } $data |
---|
734 | |
---|
735 | |
---|
736 | rename Done {} |
---|
737 | rename Get {} |
---|
738 | |
---|
739 | join [list [join $got \n] ~~~~~~~~ [join $trail \n]] \n |
---|
740 | } {[[]] |
---|
741 | [[abcdefghijklmnopqrstuvw]] |
---|
742 | [[xyz0123456789,./?><;'\|]] |
---|
743 | [[]] |
---|
744 | [[]] |
---|
745 | [[":[]\}\{`~!@#$%^&*()]] |
---|
746 | [[]] |
---|
747 | ~~~~~~~~ |
---|
748 | create/write {} *ignored* |
---|
749 | create/read {} *ignored* |
---|
750 | rblock | create/write {} {} | {} |
---|
751 | rblock | create/read {} {} | {} |
---|
752 | vvvvvvvvvvvvv |
---|
753 | rblock | query/maxRead {} -1 | {} |
---|
754 | query/maxRead {} -1 |
---|
755 | read abcdefghijklmnopqrstu abcdefghijklmnopqrstu |
---|
756 | query/maxRead {} -1 |
---|
757 | rblock | {read 23 21 :- 0} abcdefghijklmnopqrstu {} | abcdefghijklmnopqrstu |
---|
758 | rblock | query/maxRead {} -1 | abcdefghijklmnopqrstu |
---|
759 | query/maxRead {} -1 |
---|
760 | got: {[[]]} |
---|
761 | ============= |
---|
762 | vvvvvvvvvvvvv |
---|
763 | rblock | query/maxRead {} -1 | abcdefghijklmnopqrstu |
---|
764 | query/maxRead {} -1 |
---|
765 | read vwxyz0123456789,./?>< vwxyz0123456789,./?>< |
---|
766 | query/maxRead {} -1 |
---|
767 | rblock | {read 23 42 :- 23} vwxyz0123456789,./?>< abcdefghijklmnopqrstuvw | xyz0123456789,./?>< |
---|
768 | rblock | query/maxRead {} -1 | xyz0123456789,./?>< |
---|
769 | query/maxRead {} -1 |
---|
770 | got: {[[]]} {[[abcdefghijklmnopqrstuvw]]} |
---|
771 | ============= |
---|
772 | vvvvvvvvvvvvv |
---|
773 | rblock | query/maxRead {} -1 | xyz0123456789,./?>< |
---|
774 | query/maxRead {} -1 |
---|
775 | read {;'\|":[]\}\{`~!@#$%^&} {;'\|":[]\}\{`~!@#$%^&} |
---|
776 | query/maxRead {} -1 |
---|
777 | rblock | {read 23 40 :- 23} {;'\|":[]\}\{`~!@#$%^&} {xyz0123456789,./?><;'\|} | {":[]\}\{`~!@#$%^&} |
---|
778 | rblock | query/maxRead {} -1 | {":[]\}\{`~!@#$%^&} |
---|
779 | query/maxRead {} -1 |
---|
780 | got: {[[]]} {[[abcdefghijklmnopqrstuvw]]} {[[xyz0123456789,./?><;'\|]]} |
---|
781 | ============= |
---|
782 | vvvvvvvvvvvvv |
---|
783 | rblock | query/maxRead {} -1 | {":[]\}\{`~!@#$%^&} |
---|
784 | query/maxRead {} -1 |
---|
785 | read *( *( |
---|
786 | query/maxRead {} -1 |
---|
787 | rblock | {read 23 19 :- 0} *( {} | {":[]\}\{`~!@#$%^&*(} |
---|
788 | rblock | query/maxRead {} -1 | {":[]\}\{`~!@#$%^&*(} |
---|
789 | query/maxRead {} -1 |
---|
790 | got: {[[]]} {[[abcdefghijklmnopqrstuvw]]} {[[xyz0123456789,./?><;'\|]]} {[[]]} |
---|
791 | ============= |
---|
792 | vvvvvvvvvvvvv |
---|
793 | rblock | query/maxRead {} -1 | {":[]\}\{`~!@#$%^&*(} |
---|
794 | query/maxRead {} -1 |
---|
795 | read ) ) |
---|
796 | query/maxRead {} -1 |
---|
797 | rblock | {read 23 20 :- 0} ) {} | {":[]\}\{`~!@#$%^&*()} |
---|
798 | rblock | query/maxRead {} -1 | {":[]\}\{`~!@#$%^&*()} |
---|
799 | query/maxRead {} -1 |
---|
800 | got: {[[]]} {[[abcdefghijklmnopqrstuvw]]} {[[xyz0123456789,./?><;'\|]]} {[[]]} {[[]]} |
---|
801 | ============= |
---|
802 | vvvvvvvvvvvvv |
---|
803 | rblock | query/maxRead {} -1 | {":[]\}\{`~!@#$%^&*()} |
---|
804 | query/maxRead {} -1 |
---|
805 | flush/read {} {} |
---|
806 | rblock | flush/read {} {":[]\}\{`~!@#$%^&*()} | {} |
---|
807 | rblock | query/maxRead {} -1 | {} |
---|
808 | query/maxRead {} -1 |
---|
809 | got: {[[]]} {[[abcdefghijklmnopqrstuvw]]} {[[xyz0123456789,./?><;'\|]]} {[[]]} {[[]]} {[[":[]\}\{`~!@#$%^&*()]]} |
---|
810 | ============= |
---|
811 | vvvvvvvvvvvvv |
---|
812 | rblock | query/maxRead {} -1 | {} |
---|
813 | query/maxRead {} -1 |
---|
814 | got: {[[]]} {[[abcdefghijklmnopqrstuvw]]} {[[xyz0123456789,./?><;'\|]]} {[[]]} {[[]]} {[[":[]\}\{`~!@#$%^&*()]]} {[[]]} |
---|
815 | xxxxxxxxxxxxx |
---|
816 | rblock | flush/write {} {} | {} |
---|
817 | rblock | delete/write {} {} | {} |
---|
818 | rblock | delete/read {} {} | {} |
---|
819 | flush/write {} {} |
---|
820 | delete/write {} *ignored* |
---|
821 | delete/read {} *ignored*} ; # catch unescaped quote " |
---|
822 | |
---|
823 | |
---|
824 | test iogt-5.0 {EOF simulation} {testchannel unknownFailure} { |
---|
825 | set fin [open $path(dummy) r] |
---|
826 | set fout [open $path(dummyout) w] |
---|
827 | |
---|
828 | set trail [list] |
---|
829 | |
---|
830 | audit_flow trail -attach $fin |
---|
831 | stopafter_audit d trail 20 -attach $fin |
---|
832 | audit_flow trail -attach $fout |
---|
833 | |
---|
834 | fconfigure $fin -buffersize 20 |
---|
835 | fconfigure $fout -buffersize 10 |
---|
836 | |
---|
837 | fcopy $fin $fout |
---|
838 | testchannel unstack $fin |
---|
839 | |
---|
840 | # now copy the rest in the channel |
---|
841 | lappend trail {**after unstack**} |
---|
842 | |
---|
843 | fcopy $fin $fout |
---|
844 | |
---|
845 | close $fin |
---|
846 | close $fout |
---|
847 | |
---|
848 | join $trail \n |
---|
849 | } {create/read {} *ignored* |
---|
850 | counter:create/read {} {} |
---|
851 | create/write {} *ignored* |
---|
852 | counter:query/maxRead {} 20 |
---|
853 | query/maxRead {} -1 |
---|
854 | read {abcdefghijklmnopqrstuvwxyz0123456789,./?><;'\|":[]\}\{`~!@#$%^&*()_+-= |
---|
855 | } {abcdefghijklmnopqrstuvwxyz0123456789,./?><;'\|":[]\}\{`~!@#$%^&*()_+-= |
---|
856 | } |
---|
857 | query/maxRead {} -1 |
---|
858 | flush/read {} {} |
---|
859 | counter:read abcdefghijklmnopqrst abcdefghijklmnopqrst |
---|
860 | write abcdefghij abcdefghij |
---|
861 | write klmnopqrst klmnopqrst |
---|
862 | counter:query/maxRead {} 0 |
---|
863 | counter:flush/read {} {} |
---|
864 | counter:delete/read {} {} |
---|
865 | **after unstack** |
---|
866 | query/maxRead {} -1 |
---|
867 | write uvwxyz0123 uvwxyz0123 |
---|
868 | write 456789,./? 456789,./? |
---|
869 | write {><;'\|":[]} {><;'\|":[]} |
---|
870 | write {\}\{`~!@#$} {\}\{`~!@#$} |
---|
871 | write %^&*()_+-= %^&*()_+-= |
---|
872 | write { |
---|
873 | } { |
---|
874 | } |
---|
875 | query/maxRead {} -1 |
---|
876 | delete/read {} *ignored* |
---|
877 | flush/write {} {} |
---|
878 | delete/write {} *ignored*} |
---|
879 | |
---|
880 | proc constX {op data} { |
---|
881 | # replace anything coming in with a same-length string of x'es. |
---|
882 | switch -- $op { |
---|
883 | create/write - create/read - |
---|
884 | delete/write - delete/read - |
---|
885 | clear_read {;#ignore} |
---|
886 | flush/write - flush/read - |
---|
887 | write - |
---|
888 | read { |
---|
889 | return [string repeat x [string length $data]] |
---|
890 | } |
---|
891 | query/maxRead {return -1} |
---|
892 | } |
---|
893 | } |
---|
894 | |
---|
895 | proc constx {-attach channel} { |
---|
896 | testchannel transform $channel -command [namespace code constX] |
---|
897 | } |
---|
898 | |
---|
899 | test iogt-6.0 {Push back} testchannel { |
---|
900 | set f [open $path(dummy) r] |
---|
901 | |
---|
902 | # contents of dummy = "abcdefghi..." |
---|
903 | read $f 3 ; # skip behind "abc" |
---|
904 | |
---|
905 | constx -attach $f |
---|
906 | |
---|
907 | # expect to get "xxx" from the transform because |
---|
908 | # of unread "def" input to transform which returns "xxx". |
---|
909 | # |
---|
910 | # Actually the IO layer pre-read the whole file and will |
---|
911 | # read "def" directly from the buffer without bothering |
---|
912 | # to consult the newly stacked transformation. This is |
---|
913 | # wrong. |
---|
914 | |
---|
915 | set res [read $f 3] |
---|
916 | close $f |
---|
917 | set res |
---|
918 | } {xxx} |
---|
919 | |
---|
920 | test iogt-6.1 {Push back and up} {testchannel knownBug} { |
---|
921 | set f [open $path(dummy) r] |
---|
922 | |
---|
923 | # contents of dummy = "abcdefghi..." |
---|
924 | read $f 3 ; # skip behind "abc" |
---|
925 | |
---|
926 | constx -attach $f |
---|
927 | set res [read $f 3] |
---|
928 | |
---|
929 | testchannel unstack $f |
---|
930 | append res [read $f 3] |
---|
931 | close $f |
---|
932 | set res |
---|
933 | } {xxxghi} |
---|
934 | |
---|
935 | |
---|
936 | # cleanup |
---|
937 | foreach file [list dummy dummyout __echo_srv__.tcl] { |
---|
938 | removeFile $file |
---|
939 | } |
---|
940 | cleanupTests |
---|
941 | } |
---|
942 | namespace delete ::tcl::test::iogt |
---|
943 | return |
---|