1 local socket
= require
"socket"
3 host
= host
or "localhost"
7 io
.stderr
:write(string.format(...))
16 io
.stderr
:write("ERROR: ")
18 io
.stderr
:write("!\n")
23 local s
= string.format(...)
24 io
.stderr
:write("WARNING: ", s
, "\n")
28 local s
= string.format(...)
29 s
= string.gsub(s
, "\n", ";")
30 s
= string.gsub(s
, "%s+", " ")
31 s
= string.gsub(s
, "^%s*", "")
32 control
:send(s
.. "\n")
37 io
.stderr
:write("----------------------------------------------\n",
38 "testing: ", test
, "\n",
39 "----------------------------------------------\n")
42 function check_timeout(tm
, sl
, elapsed
, err
, opp
, mode
, alldone
)
45 if not err
then warn("must be buffered")
46 elseif err
== "timeout" then pass("proper timeout")
47 else fail("unexpected error '%s'", err
) end
49 if err
~= "timeout" then fail("should have timed out")
50 else pass("proper timeout") end
53 if mode
== "total" then
55 if err
~= "timeout" then fail("should have timed out")
56 else pass("proper timeout") end
57 elseif elapsed
< tm
then
62 if err
then fail("unexpected error '%s'", err
)
65 if err
~= "timeout" then fail(err
)
66 else pass("proper timeoutk") end
76 if not socket
._DEBUG
then
77 fail("Please define LUASOCKET_DEBUG and recompile LuaSocket")
80 io
.stderr
:write("----------------------------------------------\n",
81 "LuaSocket Test Procedures\n",
82 "----------------------------------------------\n")
84 start
= socket
.gettime()
87 if data
then data
:close() end
89 if data then data:close() data = nil end
90 data = server:accept()
91 data:setoption("tcp-nodelay", true)
93 data
, err
= socket
.connect(host
, port
)
94 if not data
then fail(err
) end
95 data
:setoption("tcp-nodelay", true)
98 printf("attempting control connection...")
99 control
, err
= socket
.connect(host
, port
)
100 if err
then fail(err
)
101 else pass("connected!") end
102 control
:setoption("tcp-nodelay", true)
104 ------------------------------------------------------------------------
105 function test_methods(sock
, methods
)
106 for _
, v
in pairs(methods
) do
107 if type(sock
[v
]) ~= "function" then
108 fail(sock
.class
.. " method '" .. v
.. "' not registered")
111 pass(sock
.class
.. " methods are ok")
114 ------------------------------------------------------------------------
115 function test_mixed(len
)
117 io
.stderr
:write("length " .. len
.. ": ")
118 local inter
= math
.ceil(len
/4)
119 local p1
= "unix " .. string.rep("x", inter
) .. "line\n"
120 local p2
= "dos " .. string.rep("y", inter
) .. "line\r\n"
121 local p3
= "raw " .. string.rep("z", inter
) .. "bytes"
122 local p4
= "end" .. string.rep("w", inter
) .. "bytes"
123 local bp1
, bp2
, bp3
, bp4
124 remote (string.format("str = data:receive(%d)",
125 string.len(p1
)+string.len(p2
)+string.len(p3
)+string.len(p4
)))
126 sent
, err
= data
:send(p1
..p2
..p3
..p4
)
127 if err
then fail(err
) end
128 remote
"data:send(str); data:close()"
129 bp1
, err
= data
:receive()
130 if err
then fail(err
) end
131 bp2
, err
= data
:receive()
132 if err
then fail(err
) end
133 bp3
, err
= data
:receive(string.len(p3
))
134 if err
then fail(err
) end
135 bp4
, err
= data
:receive("*a")
136 if err
then fail(err
) end
137 if bp1
.."\n" == p1
and bp2
.."\r\n" == p2
and bp3
== p3
and bp4
== p4
then
138 pass("patterns match")
139 else fail("patterns don't match") end
142 ------------------------------------------------------------------------
146 function test_asciiline(len
)
148 io
.stderr
:write("length " .. len
.. ": ")
149 local str
, str10
, back
, err
150 str
= string.rep("x", math
.mod(len
, 10))
151 str10
= string.rep("aZb.c#dAe?", math
.floor(len
/10))
153 remote
"str = data:receive()"
154 sent
, err
= data
:send(str
.."\n")
155 if err
then fail(err
) end
156 remote
"data:send(str ..'\\n')"
157 back
, err
= data
:receive()
158 if err
then fail(err
) end
159 if back
== str
then pass("lines match")
160 else fail("lines don't match") end
163 ------------------------------------------------------------------------
164 function test_rawline(len
)
166 io
.stderr
:write("length " .. len
.. ": ")
167 local str
, str10
, back
, err
168 str
= string.rep(string.char(47), math
.mod(len
, 10))
169 str10
= string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
172 remote
"str = data:receive()"
173 sent
, err
= data
:send(str
.."\n")
174 if err
then fail(err
) end
175 remote
"data:send(str..'\\n')"
176 back
, err
= data
:receive()
177 if err
then fail(err
) end
178 if back
== str
then pass("lines match")
179 else fail("lines don't match") end
182 ------------------------------------------------------------------------
183 function test_raw(len
)
185 io
.stderr
:write("length " .. len
.. ": ")
186 local half
= math
.floor(len
/2)
187 local s1
, s2
, back
, err
188 s1
= string.rep("x", half
)
189 s2
= string.rep("y", len
-half
)
190 remote (string.format("str = data:receive(%d)", len
))
191 sent
, err
= data
:send(s1
)
192 if err
then fail(err
) end
193 sent
, err
= data
:send(s2
)
194 if err
then fail(err
) end
195 remote
"data:send(str)"
196 back
, err
= data
:receive(len
)
197 if err
then fail(err
) end
198 if back
== s1
..s2
then pass("blocks match")
199 else fail("blocks don't match") end
202 ------------------------------------------------------------------------
203 function test_totaltimeoutreceive(len
, tm
, sl
)
205 local str
, err
, partial
206 printf("%d bytes, %ds total timeout, %ds pause: ", len
, tm
, sl
)
207 remote (string.format ([[
209 str = string.rep('a', %d)
211 print('server: sleeping for %ds')
213 print('server: woke up')
215 ]], 2*tm
, len
, sl
, sl
))
216 data
:settimeout(tm
, "total")
217 local t
= socket
.gettime()
218 str
, err
, partial
, elapsed
= data
:receive(2*len
)
219 check_timeout(tm
, sl
, elapsed
, err
, "receive", "total",
220 string.len(str
or partial
) == 2*len
)
223 ------------------------------------------------------------------------
224 function test_totaltimeoutsend(len
, tm
, sl
)
226 local str
, err
, total
227 printf("%d bytes, %ds total timeout, %ds pause: ", len
, tm
, sl
)
228 remote (string.format ([[
230 str = data:receive(%d)
231 print('server: sleeping for %ds')
233 print('server: woke up')
234 str = data:receive(%d)
235 ]], 2*tm
, len
, sl
, sl
, len
))
236 data
:settimeout(tm
, "total")
237 str
= string.rep("a", 2*len
)
238 total
, err
, partial
, elapsed
= data
:send(str
)
239 check_timeout(tm
, sl
, elapsed
, err
, "send", "total",
243 ------------------------------------------------------------------------
244 function test_blockingtimeoutreceive(len
, tm
, sl
)
246 local str
, err
, partial
247 printf("%d bytes, %ds blocking timeout, %ds pause: ", len
, tm
, sl
)
248 remote (string.format ([[
250 str = string.rep('a', %d)
252 print('server: sleeping for %ds')
254 print('server: woke up')
256 ]], 2*tm
, len
, sl
, sl
))
258 str
, err
, partial
, elapsed
= data
:receive(2*len
)
259 check_timeout(tm
, sl
, elapsed
, err
, "receive", "blocking",
260 string.len(str
or partial
) == 2*len
)
263 ------------------------------------------------------------------------
264 function test_blockingtimeoutsend(len
, tm
, sl
)
266 local str
, err
, total
267 printf("%d bytes, %ds blocking timeout, %ds pause: ", len
, tm
, sl
)
268 remote (string.format ([[
270 str = data:receive(%d)
271 print('server: sleeping for %ds')
273 print('server: woke up')
274 str = data:receive(%d)
275 ]], 2*tm
, len
, sl
, sl
, len
))
277 str
= string.rep("a", 2*len
)
278 total
, err
, partial
, elapsed
= data
:send(str
)
279 check_timeout(tm
, sl
, elapsed
, err
, "send", "blocking",
283 ------------------------------------------------------------------------
284 function empty_connect()
285 printf("empty connect: ")
287 if data
then data
:close() data
= nil end
289 if data then data:close() data = nil end
290 data = server:accept()
292 data
, err
= socket
.connect("", port
)
295 data
= socket
.connect(host
, port
)
297 pass("gethostbyname returns localhost on empty string...")
301 ------------------------------------------------------------------------
303 return c
:getfd() == -1 or c
:getfd() == (2^
32-1)
306 function active_close()
308 if isclosed(data
) then fail("should not be closed") end
310 if not isclosed(data
) then fail("should be closed") end
312 local udp
= socket
.udp()
313 if isclosed(udp
) then fail("should not be closed") end
315 if not isclosed(udp
) then fail("should be closed") end
319 ------------------------------------------------------------------------
320 function test_closed()
321 local back
, partial
, err
322 local str
= 'little string'
324 printf("trying read detection: ")
325 remote (string.format ([[
331 back
, err
, partial
= data
:receive()
332 if not err
then fail("should have gotten 'closed'.")
333 elseif err
~= "closed" then fail("got '"..err
.."' instead of 'closed'.")
334 elseif str
~= partial
then fail("didn't receive partial result.")
335 else pass("graceful 'closed' received") end
337 printf("trying write detection: ")
342 total
, err
, partial
= data
:send(string.rep("ugauga", 100000))
344 pass("failed: output buffer is at least %d bytes long!", total
)
345 elseif err
~= "closed" then
346 fail("got '"..err
.."' instead of 'closed'.")
348 pass("graceful 'closed' received after %d bytes were sent", partial
)
352 ------------------------------------------------------------------------
353 function test_selectbugs()
354 local r
, s
, e
= socket
.select(nil, nil, 0.1)
355 assert(type(r
) == "table" and type(s
) == "table" and
356 (e
== "timeout" or e
== "error"))
358 local udp
= socket
.udp()
360 r
, s
, e
= socket
.select({ udp
}, { udp
}, 0.1)
361 assert(type(r
) == "table" and type(s
) == "table" and
362 (e
== "timeout" or e
== "error"))
363 pass("closed sockets: ok")
364 e
= pcall(socket
.select
, "wrong", 1, 0.1)
365 assert(e
== false, tostring(e
))
366 e
= pcall(socket
.select
, {}, 1, 0.1)
367 assert(e
== false, tostring(e
))
368 pass("invalid input: ok")
370 for i
= 1, socket
._SETSIZE
+1 do
371 toomany
[#toomany
+1] = socket
.udp()
373 if #toomany
> socket
._SETSIZE
then
374 local e
= pcall(socket
.select
, toomany
, nil, 0.1)
375 assert(e
== false, tostring(e
))
376 pass("too many sockets (" .. #toomany
.. "): ok")
378 pass("unable to create enough sockets (max was "..#toomany
..")")
379 pass("try using ulimit")
381 for _
, c
in ipairs(toomany
) do c
:close() end
384 ------------------------------------------------------------------------
385 function accept_timeout()
386 printf("accept with timeout (if it hangs, it failed): ")
387 local s
, e
= socket
.bind("*", 0, 0)
389 local t
= socket
.gettime()
391 local c
, e
= s
:accept()
392 assert(not c
, "should not accept")
393 assert(e
== "timeout", string.format("wrong error message (%s)", e
))
394 t
= socket
.gettime() - t
395 assert(t
< 2, string.format("took to long to give up (%gs)", t
))
400 ------------------------------------------------------------------------
401 function connect_timeout()
402 printf("connect with timeout (if it hangs, it failed!): ")
403 local t
= socket
.gettime()
404 local c
, e
= socket
.tcp()
407 local t
= socket
.gettime()
408 local r
, e
= c
:connect("10.0.0.1", 81)
409 assert(not r
, "should not connect")
410 assert(socket
.gettime() - t
< 2, "took too long to give up.")
415 ------------------------------------------------------------------------
416 function accept_errors()
417 printf("not listening: ")
418 local d
, e
= socket
.bind("*", 0)
420 local c
, e
= socket
.tcp();
424 local r
, e
= d
:accept()
427 printf("not supported: ")
428 local c
, e
= socket
.udp()
431 local r
, e
= d
:accept()
436 ------------------------------------------------------------------------
437 function connect_errors()
438 printf("connection refused: ")
439 local c
, e
= socket
.connect("localhost", 1);
442 printf("host not found: ")
443 local c
, e
= socket
.connect("host.is.invalid", 1);
444 assert(not c
and e
, e
)
448 ------------------------------------------------------------------------
449 function rebind_test()
450 --local c ,c1 = socket.bind("localhost", 0)
451 local c
,c1
= socket
.bind("127.0.0.1", 0)
452 if not c
then pass ("failed to bind! " .. tostring(c
) .. ' ' .. tostring(c1
)) return end
455 local i
, p
= c
:getsockname()
456 local s
, e
= socket
.tcp()
458 s
:setoption("reuseaddr", false)
459 r
, e
= s
:bind("localhost", p
)
460 assert(not r
, "managed to rebind!")
465 ------------------------------------------------------------------------
466 function getstats_test()
470 local c
= math
.random(1, 100)
471 remote (string.format ([[
472 str = data:receive(%d)
475 data
:send(string.rep("a", c
))
478 local r
, s
, a
= data
:getstats()
479 assert(r
== t
, "received count failed" .. tostring(r
)
480 .. "/" .. tostring(t
))
481 assert(s
== t
, "sent count failed" .. tostring(s
)
482 .. "/" .. tostring(t
))
488 ------------------------------------------------------------------------
489 function test_nonblocking(size
)
491 printf("testing " .. 2*size
.. " bytes: ")
492 remote(string.format([[
493 data:send(string.rep("a", %d))
495 data:send(string.rep("b", %d) .. "\n")
497 local err
= "timeout"
502 str
, err
, part
= data
:receive("*l", part
)
503 if err
~= "timeout" then break end
505 assert(str
== (string.rep("a", size
) .. string.rep("b", size
)))
507 remote(string.format([[
508 str = data:receive(%d)
510 str = data:receive(2*%d, str)
516 ret
, err
, start
= data
:send(str
, start
+1)
517 if err
~= "timeout" then break end
521 local back
= data
:receive(2*size
)
522 assert(back
== str
, "'" .. back
.. "' vs '" .. str
.. "'")
526 ------------------------------------------------------------------------
527 function test_readafterclose()
528 local back
, partial
, err
529 local str
= 'little string'
531 printf("trying repeated '*a' pattern")
532 remote (string.format ([[
537 back
, err
, partial
= data
:receive("*a")
538 assert(back
== str
, "unexpected data read")
539 back
, err
, partial
= data
:receive("*a")
540 assert(back
== nil and err
== "closed", "should have returned 'closed'")
543 printf("trying active close before '*a'")
544 remote (string.format ([[
549 back
, err
, partial
= data
:receive("*a")
550 assert(back
== nil and err
== "closed", "should have returned 'closed'")
553 printf("trying active close before '*l'")
554 remote (string.format ([[
559 back
, err
, partial
= data
:receive()
560 assert(back
== nil and err
== "closed", "should have returned 'closed'")
563 printf("trying active close before raw 1")
564 remote (string.format ([[
569 back
, err
, partial
= data
:receive(1)
570 assert(back
== nil and err
== "closed", "should have returned 'closed'")
573 printf("trying active close before raw 0")
574 remote (string.format ([[
579 back
, err
, partial
= data
:receive(0)
580 assert(back
== nil and err
== "closed", "should have returned 'closed'")
584 ------------------------------------------------------------------------
585 function test_writeafterclose()
586 local str
= 'little string'
588 remote (string.format ([[
592 local sent
, err
, errsent
594 sent
, err
, errsent
, time
= data
:send(str
)
596 assert(err
== "closed", "should have returned 'closed'")
600 ------------------------------------------------------------------------
602 function test_partialrecv()
603 local str
= 'little string'
609 back
, err
= data
:receive(10, "123456")
610 assert(back
== "1234567890", "failed on exact mixed length")
611 back
, err
= data
:receive(8, "87654321")
612 assert(back
== "87654321", "failed on exact length")
613 back
, err
= data
:receive(4, "87654321")
614 assert(back
== "87654321", "failed on smaller length")
618 ------------------------------------------------------------------------
619 test("method registration")
621 local tcp_methods
= {
644 test_methods(socket
.tcp(), tcp_methods
)
645 test_methods(socket
.tcp6(), tcp_methods
)
647 local udp_methods
= {
667 ------------------------------------------------------------------------
668 test_methods(socket
.udp(), udp_methods
)
669 test_methods(socket
.udp6(), udp_methods
)
671 test("partial receive")
674 test("select function")
677 test("read after close")
678 test_readafterclose()
680 test("write after close")
681 test_writeafterclose()
683 test("connect function")
691 test("active close: ")
694 test("closed connection detection: ")
697 test("accept function: ")
701 test("getstats test")
704 test("character line")
709 test_asciiline(80199)
710 test_asciiline(8000000)
711 test_asciiline(80199)
717 test("mixed patterns")
734 test_rawline(8000000)
754 test("non-blocking transfer")
757 test_nonblocking(200)
758 test_nonblocking(4091)
759 test_nonblocking(80199)
760 test_nonblocking(800000)
761 test_nonblocking(80199)
762 test_nonblocking(4091)
763 test_nonblocking(200)
767 test("total timeout on send")
768 test_totaltimeoutsend(800091, 1, 3)
769 test_totaltimeoutsend(800091, 2, 3)
770 test_totaltimeoutsend(800091, 5, 2)
771 test_totaltimeoutsend(800091, 3, 1)
773 test("total timeout on receive")
774 test_totaltimeoutreceive(800091, 1, 3)
775 test_totaltimeoutreceive(800091, 2, 3)
776 test_totaltimeoutreceive(800091, 3, 2)
777 test_totaltimeoutreceive(800091, 3, 1)
779 test("blocking timeout on send")
780 test_blockingtimeoutsend(800091, 1, 3)
781 test_blockingtimeoutsend(800091, 2, 3)
782 test_blockingtimeoutsend(800091, 3, 2)
783 test_blockingtimeoutsend(800091, 3, 1)
785 test("blocking timeout on receive")
786 test_blockingtimeoutreceive(800091, 1, 3)
787 test_blockingtimeoutreceive(800091, 2, 3)
788 test_blockingtimeoutreceive(800091, 3, 2)
789 test_blockingtimeoutreceive(800091, 3, 1)
791 test("shutting server down")
795 test(string.format("done in %.2fs", socket
.gettime() - start
))