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 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
|
source [file dirname [info script]]/testing.tcl
needs constraint jim
constraint cmd socket
constraint cmd os.fork
constraint expr posixaio {$tcl_platform(platform) eq {unix} && !$tcl_platform(bootstrap)}
# Create and open in binary mode for compatibility between Windows and Unix
set f [open testdata.in wb]
$f puts test-data
$f close
# create a test file file with several lines
set f [open copy.in wb]
$f puts line1
$f puts line2
$f puts line3
$f close
set f [open testdata.in rb]
defer {
$f close
file delete testdata.in
file delete copy.in
file delete copy.out
}
test aio-1.1 {seek usage} -body {
$f seek
} -returnCodes error -match glob -result {wrong # args: should be "* seek offset ?start|current|end"}
test aio-1.2 {seek start} -body {
$f seek 2
$f tell
} -result {2}
test aio-1.3 {seek start} -body {
$f seek 4 start
$f tell
} -result {4}
test aio-1.4 {read after seek} -body {
set c [$f read 1]
list $c [$f tell]
} -result {- 5}
test aio-1.5 {seek backwards} -body {
$f seek -2 current
set c [$f read 1]
list $c [$f tell]
} -result {t 4}
test aio-1.6 {seek from end} -body {
$f seek -2 end
set c [$f read 2]
list $c [$f tell]
} -result [list "a\n" 10]
test aio-1.7 {seek usage} -body {
$f seek 4 bad
} -returnCodes error -match glob -result {wrong # args: should be "* seek offset ?start|current|end"}
test aio-1.8 {seek usage} -body {
$f seek badint
} -returnCodes error -match glob -result {expected integer but got "badint"}
test aio-1.9 {seek bad pos} -body {
$f seek -20
} -returnCodes error -match glob -result {testdata.in: Invalid argument}
test aio-2.1 {read usage} -body {
$f read -nonoption
} -returnCodes error -result {bad option "-nonoption": must be -nonewline, or -pending}
test aio-2.2 {read usage} -body {
$f read badint
} -returnCodes error -result {expected integer but got "badint"}
test aio-2.3 {read -ve len} -body {
$f read " -20"
} -returnCodes error -result {invalid parameter: negative len}
test aio-2.4 {read too many args} -body {
$f read 20 extra
} -returnCodes error -match glob -result {wrong # args: should be "* read ?-nonewline|len?"}
test aio-3.1 {copy to invalid fh} -body {
$f copy lambda
} -returnCodes error -result {Not a filehandle: "lambda"}
test aio-3.2 {copy bad length} -body {
$f copy stdout invalid
} -returnCodes error -result {expected integer but got "invalid"}
set badvar a
test aio-4.1 {gets invalid var} -body {
$f gets badvar(abc)
} -returnCodes error -result {can't set "badvar(abc)": variable isn't array}
test aio-5.1 {puts usage} -body {
stdout puts -badopt abc
} -returnCodes error -result {wrong # args: should be "stdout puts ?-nonewline? str"}
test aio-6.1 {eof} {
$f seek 0
$f eof
} {0}
test aio-6.2 {eof} {
# eof won't trigger until we try to read
$f seek 0 end
$f eof
} {0}
test aio-6.3 {eof} {
$f read 1
$f eof
} {1}
test aio-7.1 {close args} -constraints socket -body {
$f close badopt
} -returnCodes error -result {bad option "badopt": must be -nodelete, r, or w}
test aio-7.2 {close w on non-socket} -constraints socket -body {
$f close w
} -returnCodes error -match regexp -result {(bad|socket)}
test aio-7.3 {close -nodelete on non-socket} -constraints socket -body {
$f close -nodelete
} -returnCodes error -result {not supported}
test aio-8.1 {filename} {
$f filename
} testdata.in
test aio-9.1 {open: posix modes} -constraints posixaio -body {
set in [open testdata.in RDONLY]
set buf [$in gets]
$in close
set buf
} -result {test-data}
test aio-9.2 {open: posix modes, bad modes} -constraints posixaio -body {
open testdata.in {CREAT TRUNC}
} -returnCodes error -result {testdata.in: invalid open mode 'CREAT TRUNC'}
test aio-9.3 {open: posix modes, bad modes} -constraints posixaio -body {
open testdata.in {WRONG TRUNC}
} -returnCodes error -result {bad access mode "WRONG": must be APPEND, BINARY, CREAT, EXCL, NOCTTY, RDONLY, RDWR, TRUNC, or WRONLY}
test aio-9.4 {open: posix modes} -constraints posixaio -cleanup {
file delete testdata.out
} -body {
set out [open testdata.out {WRONLY CREAT TRUNC}]
$out puts write-data
$out close
# Now open for readwrite without truncate
set io [open testdata.out {RDWR CREAT}]
set buf [$io gets]
$io close
set buf
} -result {write-data}
test aio-10.1 {open: -noclose} -constraints os.fork -cleanup {
file delete testdata.out
} -body {
# Keep this file descriptor open for children
set f [open testdata.out -noclose w]
$f puts parent
$f flush
# Now the child process can write to the same file via the file descriptor
exec sh -c "echo child >&[$f getfd]"
$f close
set in [open testdata.out]
set lines [list [$in gets] [$in gets]]
$in close
set lines
} -result {parent child}
test copyto-1.1 {basic copyto} {
set in [open copy.in]
set out [open copy.out w]
$in copyto $out
$in close
$out close
set ff [open copy.out]
set result [list [$ff gets] [$ff gets] [$ff gets]]
$ff close
set result
} {line1 line2 line3}
test copyto-1.2 {copyto with limit} {
set in [open copy.in]
set out [open copy.out w]
$in copyto $out 8
$in close
$out close
set ff [open copy.out]
set result [list [$ff gets] [$ff gets] [$ff gets]]
$ff close
set result
} {line1 li {}}
test copyto-1.3 {copyto after gets} {
set in [open copy.in]
set out [open copy.out w]
$in gets
$in copyto $out
$in close
$out close
set ff [open copy.out]
set result [list [$ff gets] [$ff gets] [$ff gets]]
$ff close
set result
} {line2 line3 {}}
test copyto-1.4 {copyto after read} {
set in [open copy.in]
$in read 3
set out [open copy.out w]
$in copyto $out
$in close
$out close
set ff [open copy.out]
set result [list [$ff gets] [$ff gets] [$ff gets]]
$ff close
set result
} {e1 line2 line3}
test copyto-1.5 {copyto after gets, seek} {
set in [open copy.in]
$in gets
$in seek 2 start
set out [open copy.out w]
$in copyto $out
$in close
$out close
set ff [open copy.out]
set result [list [$ff gets] [$ff gets] [$ff gets]]
$ff close
set result
} {ne1 line2 line3}
test copyto-1.6 {copyto from pipe} {
set in [open "|cat copy.in"]
set out [open copy.out w]
$in copyto $out
$in close
$out close
set ff [open copy.out]
set result [list [$ff gets] [$ff gets] [$ff gets]]
$ff close
set result
} {line1 line2 line3}
test copyto-1.6 {copyto to pipe} {
set out [open "|cat >copy.out" w]
set in [open copy.in]
$in copyto $out
$in close
$out close
set ff [open copy.out]
set result [list [$ff gets] [$ff gets] [$ff gets]]
$ff close
set result
} {line1 line2 line3}
# Creates a child process and returns {pid writehandle}
# The child expects to read $numlines lines of input and exits with a return
# code of 0 if ok
proc child_reader {numlines} {
# create a pipe with the child as a slightly slow reader
lassign [socket pipe] r w
set pid [os.fork]
if {$pid == 0} {
# child
$w close
# sleep a moment to make sure the parent fills up the send buffer
sleep 0.5
set n 0
while {[$r gets buf] >= 0} {
incr n
}
#puts "child got $n/$numlines lines"
$r close
if {$n == $numlines} {
# This is what we expect
exit 99
}
# This is not expected
exit 98
}
# parent
$r close
list $pid $w
}
test autoflush-1.1 {pipe writer, blocking} -constraints {socket os.fork} -body {
lassign [child_reader 10000] pid w
# Send data fast enough to fill up the send buffer
loop i 10000 {
$w puts "this is line $i"
}
# No autoflush needed. The write won't return
# until queued
$w close
lassign [wait $pid] - - rc
list $rc
} -result {99}
test autoflush-1.2 {pipe writer, non blocking} -constraints {socket os.fork} -body {
lassign [child_reader 10000] pid w
$w ndelay 1
# Send data fast enough to fill up the send buffer
# With older jimtcl this would return an error "pipe: Resource temporarily unavailable"
loop i 10000 {
$w puts "this is line $i"
}
# Now data should still be queued, wait for autoflush
lassign [time {
after idle {}
vwait done
}] t1
# puts "autoflush finished in ${t1}us, closing pipe"
$w close
lassign [wait $pid] - - rc
list $rc $t1
} -match glob -result {99 *}
testreport
|