mirror of
https://github.com/minetest-mods/irc.git
synced 2025-06-28 14:16:09 +02:00
initial commit
This commit is contained in:
109
etc/tests/luairc/luabot.lua
Executable file
109
etc/tests/luairc/luabot.lua
Executable file
@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local irc = require 'irc'
|
||||
irc.DEBUG = true
|
||||
|
||||
local nick = "doylua"
|
||||
|
||||
local envs = {}
|
||||
|
||||
local function create_env()
|
||||
return {
|
||||
_VERSION = _VERSION,
|
||||
assert = assert,
|
||||
collectgarbage = collectgarbage,
|
||||
error = error,
|
||||
getfenv = getfenv,
|
||||
getmetatable = getmetatable,
|
||||
ipairs = ipairs,
|
||||
loadstring = loadstring,
|
||||
next = next,
|
||||
pairs = pairs,
|
||||
pcall = pcall,
|
||||
rawequal = rawequal,
|
||||
rawget = rawget,
|
||||
rawset = rawset,
|
||||
select = select,
|
||||
setfenv = setfenv,
|
||||
setmetatable = setmetatable,
|
||||
tonumber = tonumber,
|
||||
tostring = tostring,
|
||||
type = type,
|
||||
unpack = unpack,
|
||||
xpcall = xpcall,
|
||||
coroutine = coroutine,
|
||||
math = math,
|
||||
string = string,
|
||||
table = table,
|
||||
}
|
||||
end
|
||||
|
||||
local commands = {
|
||||
eval = function(target, from, code)
|
||||
code = code:gsub("^=", "return ")
|
||||
local fn, err = loadstring(code)
|
||||
if not fn then
|
||||
irc.say(target, from .. ": Error loading code: " .. code .. err:match(".*(:.-)$"))
|
||||
return
|
||||
else
|
||||
setfenv(fn, envs[from])
|
||||
local result = {pcall(fn)}
|
||||
local success = table.remove(result, 1)
|
||||
if not success then
|
||||
irc.say(target, from .. ": Error running code: " .. code .. result[1]:match(".*(:.-)$"))
|
||||
else
|
||||
if result[1] == nil then
|
||||
irc.say(target, from .. ": nil")
|
||||
else
|
||||
irc.say(target, from .. ": " .. table.concat(result, ", "))
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
clear = function(target, from)
|
||||
irc.say(target, from .. ": Clearing your environment")
|
||||
envs[from] = create_env()
|
||||
end,
|
||||
help = function(target, from, arg)
|
||||
if arg == "" or not arg then
|
||||
irc.say(target, from .. ": Commands: !clear, !eval, !help")
|
||||
elseif arg == "eval" then
|
||||
irc.say(target, from .. ": Evaluates a Lua statement in your own persistent environment")
|
||||
elseif arg == "clear" then
|
||||
irc.say(target, from .. ": Clears your personal environment")
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
irc.register_callback("connect", function()
|
||||
irc.join("#doytest")
|
||||
end)
|
||||
|
||||
irc.register_callback("channel_msg", function(channel, from, message)
|
||||
message = message:gsub("^" .. nick .. "[:,>] ", "!eval ")
|
||||
local is_cmd, cmd, arg = message:match("^(!)([%w_]+) ?(.-)$")
|
||||
if is_cmd and commands[cmd] then
|
||||
envs[from] = envs[from] or create_env()
|
||||
commands[cmd](channel.name, from, arg)
|
||||
end
|
||||
end)
|
||||
|
||||
irc.register_callback("private_msg", function(from, message)
|
||||
message = message:gsub("^" .. nick .. "[:,>] ", "!eval ")
|
||||
local is_cmd, cmd, arg = message:match("^(!)([%w_]+) ?(.-)$")
|
||||
envs[from] = envs[from] or create_env()
|
||||
if is_cmd and commands[cmd] then
|
||||
commands[cmd](from, from, arg)
|
||||
else
|
||||
commands["eval"](from, from, message)
|
||||
end
|
||||
end)
|
||||
|
||||
irc.register_callback("nick_change", function(from, old_nick)
|
||||
if envs[old_nick] and not envs[from] then
|
||||
envs[from] = envs[old_nick]
|
||||
envs[old_nick] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
irc.connect{network = "irc.freenode.net", nick = nick, pass = "doylua"}
|
228
etc/tests/luairc/test.lua
Executable file
228
etc/tests/luairc/test.lua
Executable file
@ -0,0 +1,228 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
local irc = require "irc"
|
||||
local dcc = require "irc.dcc"
|
||||
|
||||
irc.DEBUG = true
|
||||
|
||||
local ip_prog = io.popen("get_ip")
|
||||
local ip = ip_prog:read()
|
||||
ip_prog:close()
|
||||
irc.set_ip(ip)
|
||||
|
||||
local function print_state()
|
||||
for chan in irc.channels() do
|
||||
print(chan..": Channel ops: "..table.concat(chan:ops(), " "))
|
||||
print(chan..": Channel voices: "..table.concat(chan:voices(), " "))
|
||||
print(chan..": Channel normal users: "..table.concat(chan:users(), " "))
|
||||
print(chan..": All channel members: "..table.concat(chan:members(), " "))
|
||||
end
|
||||
end
|
||||
|
||||
local function on_connect()
|
||||
print("Joining channel #doytest...")
|
||||
irc.join("#doytest")
|
||||
print("Joining channel #doytest2...")
|
||||
irc.join("#doytest2")
|
||||
end
|
||||
irc.register_callback("connect", on_connect)
|
||||
|
||||
local function on_me_join(chan)
|
||||
print("Join to " .. chan .. " complete.")
|
||||
print(chan .. ": Channel type: " .. chan.chanmode)
|
||||
if chan.topic.text and chan.topic.text ~= "" then
|
||||
print(chan .. ": Channel topic: " .. chan.topic.text)
|
||||
print(" Set by " .. chan.topic.user ..
|
||||
" at " .. os.date("%c", chan.topic.time))
|
||||
end
|
||||
irc.act(chan.name, "is here")
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("me_join", on_me_join)
|
||||
|
||||
local function on_join(chan, user)
|
||||
print("I saw a join to " .. chan)
|
||||
if tostring(user) ~= "doylua" then
|
||||
irc.say(tostring(chan), "Hi, " .. user)
|
||||
end
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("join", on_join)
|
||||
|
||||
local function on_part(chan, user, part_msg)
|
||||
print("I saw a part from " .. chan .. " saying " .. part_msg)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("part", on_part)
|
||||
|
||||
local function on_nick_change(new_nick, old_nick)
|
||||
print("I saw a nick change: " .. old_nick .. " -> " .. new_nick)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("nick_change", on_nick_change)
|
||||
|
||||
local function on_kick(chan, user)
|
||||
print("I saw a kick in " .. chan)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("kick", on_kick)
|
||||
|
||||
local function on_quit(chan, user)
|
||||
print("I saw a quit from " .. chan)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("quit", on_quit)
|
||||
|
||||
local function whois_cb(cb_data)
|
||||
print("WHOIS data for " .. cb_data.nick)
|
||||
if cb_data.user then print("Username: " .. cb_data.user) end
|
||||
if cb_data.host then print("Host: " .. cb_data.host) end
|
||||
if cb_data.realname then print("Realname: " .. cb_data.realname) end
|
||||
if cb_data.server then print("Server: " .. cb_data.server) end
|
||||
if cb_data.serverinfo then print("Serverinfo: " .. cb_data.serverinfo) end
|
||||
if cb_data.away_msg then print("Awaymsg: " .. cb_data.away_msg) end
|
||||
if cb_data.is_oper then print(nick .. "is an IRCop") end
|
||||
if cb_data.idle_time then print("Idletime: " .. cb_data.idle_time) end
|
||||
if cb_data.channels then
|
||||
print("Channel list for " .. cb_data.nick .. ":")
|
||||
for _, channel in ipairs(cb_data.channels) do print(channel) end
|
||||
end
|
||||
end
|
||||
|
||||
local function serverversion_cb(cb_data)
|
||||
print("VERSION data for " .. cb_data.server)
|
||||
print("Version: " .. cb_data.version)
|
||||
print("Comments: " .. cb_data.comments)
|
||||
end
|
||||
|
||||
local function ping_cb(cb_data)
|
||||
print("CTCP PING for " .. cb_data.nick)
|
||||
print("Roundtrip time: " .. cb_data.time .. "s")
|
||||
end
|
||||
|
||||
local function time_cb(cb_data)
|
||||
print("CTCP TIME for " .. cb_data.nick)
|
||||
print("Localtime: " .. cb_data.time)
|
||||
end
|
||||
|
||||
local function version_cb(cb_data)
|
||||
print("CTCP VERSION for " .. cb_data.nick)
|
||||
print("Version: " .. cb_data.version)
|
||||
end
|
||||
|
||||
local function stime_cb(cb_data)
|
||||
print("TIME for " .. cb_data.server)
|
||||
print("Server time: " .. cb_data.time)
|
||||
end
|
||||
|
||||
local function on_channel_msg(chan, from, msg)
|
||||
if from == "doy" then
|
||||
if msg == "leave" then
|
||||
irc.part(chan.name)
|
||||
return
|
||||
elseif msg:sub(1, 3) == "op " then
|
||||
chan:op(msg:sub(4))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "deop " then
|
||||
chan:deop(msg:sub(6))
|
||||
return
|
||||
elseif msg:sub(1, 6) == "voice " then
|
||||
chan:voice(msg:sub(7))
|
||||
return
|
||||
elseif msg:sub(1, 8) == "devoice " then
|
||||
chan:devoice(msg:sub(9))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "kick " then
|
||||
chan:kick(msg:sub(6))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "send " then
|
||||
dcc.send(from, msg:sub(6))
|
||||
return
|
||||
elseif msg:sub(1, 6) == "whois " then
|
||||
irc.whois(whois_cb, msg:sub(7))
|
||||
return
|
||||
elseif msg:sub(1, 8) == "sversion" then
|
||||
irc.server_version(serverversion_cb)
|
||||
return
|
||||
elseif msg:sub(1, 5) == "ping " then
|
||||
irc.ctcp_ping(ping_cb, msg:sub(6))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "time " then
|
||||
irc.ctcp_time(time_cb, msg:sub(6))
|
||||
return
|
||||
elseif msg:sub(1, 8) == "version " then
|
||||
irc.ctcp_version(version_cb, msg:sub(9))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "stime" then
|
||||
irc.server_time(stime_cb)
|
||||
return
|
||||
elseif msg:sub(1, 6) == "trace " then
|
||||
irc.trace(trace_cb, msg:sub(7))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "trace" then
|
||||
irc.trace(trace_cb)
|
||||
return
|
||||
end
|
||||
end
|
||||
if from ~= "doylua" then
|
||||
irc.say(chan.name, from .. ": " .. msg)
|
||||
end
|
||||
end
|
||||
irc.register_callback("channel_msg", on_channel_msg)
|
||||
|
||||
local function on_private_msg(from, msg)
|
||||
if from == "doy" then
|
||||
if msg == "leave" then
|
||||
irc.quit("gone")
|
||||
return
|
||||
elseif msg:sub(1, 5) == "send " then
|
||||
dcc.send(from, msg:sub(6))
|
||||
return
|
||||
end
|
||||
end
|
||||
if from ~= "doylua" then
|
||||
irc.say(from, msg)
|
||||
end
|
||||
end
|
||||
irc.register_callback("private_msg", on_private_msg)
|
||||
|
||||
local function on_channel_act(chan, from, msg)
|
||||
irc.act(chan.name, "jumps on " .. from)
|
||||
end
|
||||
irc.register_callback("channel_act", on_channel_act)
|
||||
|
||||
local function on_private_act(from, msg)
|
||||
irc.act(from, "jumps on you")
|
||||
end
|
||||
irc.register_callback("private_act", on_private_act)
|
||||
|
||||
local function on_op(chan, from, nick)
|
||||
print(nick .. " was opped in " .. chan .. " by " .. from)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("op", on_op)
|
||||
|
||||
local function on_deop(chan, from, nick)
|
||||
print(nick .. " was deopped in " .. chan .. " by " .. from)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("deop", on_deop)
|
||||
|
||||
local function on_voice(chan, from, nick)
|
||||
print(nick .. " was voiced in " .. chan .. " by " .. from)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("voice", on_voice)
|
||||
|
||||
local function on_devoice(chan, from, nick)
|
||||
print(nick .. " was devoiced in " .. chan .. " by " .. from)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("devoice", on_devoice)
|
||||
|
||||
local function on_dcc_send()
|
||||
return true
|
||||
end
|
||||
irc.register_callback("dcc_send", on_dcc_send)
|
||||
|
||||
irc.connect{network = "irc.freenode.net", nick = "doylua"}
|
12
etc/tests/luasocket/README
Normal file
12
etc/tests/luasocket/README
Normal file
@ -0,0 +1,12 @@
|
||||
This provides the automated test scripts used to make sure the library
|
||||
is working properly.
|
||||
|
||||
The files provided are:
|
||||
|
||||
testsrvr.lua -- test server
|
||||
testclnt.lua -- test client
|
||||
|
||||
To run these tests, just run lua on the server and then on the client.
|
||||
|
||||
Good luck,
|
||||
Diego.
|
655
etc/tests/luasocket/testclnt.lua
Normal file
655
etc/tests/luasocket/testclnt.lua
Normal file
@ -0,0 +1,655 @@
|
||||
local socket = require"socket"
|
||||
|
||||
host = host or "localhost"
|
||||
port = port or "8383"
|
||||
|
||||
function pass(...)
|
||||
local s = string.format(unpack(arg))
|
||||
io.stderr:write(s, "\n")
|
||||
end
|
||||
|
||||
function fail(...)
|
||||
local s = string.format(unpack(arg))
|
||||
io.stderr:write("ERROR: ", s, "!\n")
|
||||
socket.sleep(3)
|
||||
os.exit()
|
||||
end
|
||||
|
||||
function warn(...)
|
||||
local s = string.format(unpack(arg))
|
||||
io.stderr:write("WARNING: ", s, "\n")
|
||||
end
|
||||
|
||||
function remote(...)
|
||||
local s = string.format(unpack(arg))
|
||||
s = string.gsub(s, "\n", ";")
|
||||
s = string.gsub(s, "%s+", " ")
|
||||
s = string.gsub(s, "^%s*", "")
|
||||
control:send(s .. "\n")
|
||||
control:receive()
|
||||
end
|
||||
|
||||
function test(test)
|
||||
io.stderr:write("----------------------------------------------\n",
|
||||
"testing: ", test, "\n",
|
||||
"----------------------------------------------\n")
|
||||
end
|
||||
|
||||
function check_timeout(tm, sl, elapsed, err, opp, mode, alldone)
|
||||
if tm < sl then
|
||||
if opp == "send" then
|
||||
if not err then warn("must be buffered")
|
||||
elseif err == "timeout" then pass("proper timeout")
|
||||
else fail("unexpected error '%s'", err) end
|
||||
else
|
||||
if err ~= "timeout" then fail("should have timed out")
|
||||
else pass("proper timeout") end
|
||||
end
|
||||
else
|
||||
if mode == "total" then
|
||||
if elapsed > tm then
|
||||
if err ~= "timeout" then fail("should have timed out")
|
||||
else pass("proper timeout") end
|
||||
elseif elapsed < tm then
|
||||
if err then fail(err)
|
||||
else pass("ok") end
|
||||
else
|
||||
if alldone then
|
||||
if err then fail("unexpected error '%s'", err)
|
||||
else pass("ok") end
|
||||
else
|
||||
if err ~= "timeout" then fail(err)
|
||||
else pass("proper timeoutk") end
|
||||
end
|
||||
end
|
||||
else
|
||||
if err then fail(err)
|
||||
else pass("ok") end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not socket._DEBUG then
|
||||
fail("Please define LUASOCKET_DEBUG and recompile LuaSocket")
|
||||
end
|
||||
|
||||
io.stderr:write("----------------------------------------------\n",
|
||||
"LuaSocket Test Procedures\n",
|
||||
"----------------------------------------------\n")
|
||||
|
||||
start = socket.gettime()
|
||||
|
||||
function reconnect()
|
||||
io.stderr:write("attempting data connection... ")
|
||||
if data then data:close() end
|
||||
remote [[
|
||||
if data then data:close() data = nil end
|
||||
data = server:accept()
|
||||
data:setoption("tcp-nodelay", true)
|
||||
]]
|
||||
data, err = socket.connect(host, port)
|
||||
if not data then fail(err)
|
||||
else pass("connected!") end
|
||||
data:setoption("tcp-nodelay", true)
|
||||
end
|
||||
|
||||
pass("attempting control connection...")
|
||||
control, err = socket.connect(host, port)
|
||||
if err then fail(err)
|
||||
else pass("connected!") end
|
||||
control:setoption("tcp-nodelay", true)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_methods(sock, methods)
|
||||
for _, v in methods do
|
||||
if type(sock[v]) ~= "function" then
|
||||
fail(sock.class .. " method '" .. v .. "' not registered")
|
||||
end
|
||||
end
|
||||
pass(sock.class .. " methods are ok")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_mixed(len)
|
||||
reconnect()
|
||||
local inter = math.ceil(len/4)
|
||||
local p1 = "unix " .. string.rep("x", inter) .. "line\n"
|
||||
local p2 = "dos " .. string.rep("y", inter) .. "line\r\n"
|
||||
local p3 = "raw " .. string.rep("z", inter) .. "bytes"
|
||||
local p4 = "end" .. string.rep("w", inter) .. "bytes"
|
||||
local bp1, bp2, bp3, bp4
|
||||
remote (string.format("str = data:receive(%d)",
|
||||
string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4)))
|
||||
sent, err = data:send(p1..p2..p3..p4)
|
||||
if err then fail(err) end
|
||||
remote "data:send(str); data:close()"
|
||||
bp1, err = data:receive()
|
||||
if err then fail(err) end
|
||||
bp2, err = data:receive()
|
||||
if err then fail(err) end
|
||||
bp3, err = data:receive(string.len(p3))
|
||||
if err then fail(err) end
|
||||
bp4, err = data:receive("*a")
|
||||
if err then fail(err) end
|
||||
if bp1.."\n" == p1 and bp2.."\r\n" == p2 and bp3 == p3 and bp4 == p4 then
|
||||
pass("patterns match")
|
||||
else fail("patterns don't match") end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_asciiline(len)
|
||||
reconnect()
|
||||
local str, str10, back, err
|
||||
str = string.rep("x", math.mod(len, 10))
|
||||
str10 = string.rep("aZb.c#dAe?", math.floor(len/10))
|
||||
str = str .. str10
|
||||
remote "str = data:receive()"
|
||||
sent, err = data:send(str.."\n")
|
||||
if err then fail(err) end
|
||||
remote "data:send(str ..'\\n')"
|
||||
back, err = data:receive()
|
||||
if err then fail(err) end
|
||||
if back == str then pass("lines match")
|
||||
else fail("lines don't match") end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_rawline(len)
|
||||
reconnect()
|
||||
local str, str10, back, err
|
||||
str = string.rep(string.char(47), math.mod(len, 10))
|
||||
str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
|
||||
math.floor(len/10))
|
||||
str = str .. str10
|
||||
remote "str = data:receive()"
|
||||
sent, err = data:send(str.."\n")
|
||||
if err then fail(err) end
|
||||
remote "data:send(str..'\\n')"
|
||||
back, err = data:receive()
|
||||
if err then fail(err) end
|
||||
if back == str then pass("lines match")
|
||||
else fail("lines don't match") end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_raw(len)
|
||||
reconnect()
|
||||
local half = math.floor(len/2)
|
||||
local s1, s2, back, err
|
||||
s1 = string.rep("x", half)
|
||||
s2 = string.rep("y", len-half)
|
||||
remote (string.format("str = data:receive(%d)", len))
|
||||
sent, err = data:send(s1)
|
||||
if err then fail(err) end
|
||||
sent, err = data:send(s2)
|
||||
if err then fail(err) end
|
||||
remote "data:send(str)"
|
||||
back, err = data:receive(len)
|
||||
if err then fail(err) end
|
||||
if back == s1..s2 then pass("blocks match")
|
||||
else fail("blocks don't match") end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_totaltimeoutreceive(len, tm, sl)
|
||||
reconnect()
|
||||
local str, err, partial
|
||||
pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl)
|
||||
remote (string.format ([[
|
||||
data:settimeout(%d)
|
||||
str = string.rep('a', %d)
|
||||
data:send(str)
|
||||
print('server: sleeping for %ds')
|
||||
socket.sleep(%d)
|
||||
print('server: woke up')
|
||||
data:send(str)
|
||||
]], 2*tm, len, sl, sl))
|
||||
data:settimeout(tm, "total")
|
||||
local t = socket.gettime()
|
||||
str, err, partial, elapsed = data:receive(2*len)
|
||||
check_timeout(tm, sl, elapsed, err, "receive", "total",
|
||||
string.len(str or partial) == 2*len)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_totaltimeoutsend(len, tm, sl)
|
||||
reconnect()
|
||||
local str, err, total
|
||||
pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl)
|
||||
remote (string.format ([[
|
||||
data:settimeout(%d)
|
||||
str = data:receive(%d)
|
||||
print('server: sleeping for %ds')
|
||||
socket.sleep(%d)
|
||||
print('server: woke up')
|
||||
str = data:receive(%d)
|
||||
]], 2*tm, len, sl, sl, len))
|
||||
data:settimeout(tm, "total")
|
||||
str = string.rep("a", 2*len)
|
||||
total, err, partial, elapsed = data:send(str)
|
||||
check_timeout(tm, sl, elapsed, err, "send", "total",
|
||||
total == 2*len)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_blockingtimeoutreceive(len, tm, sl)
|
||||
reconnect()
|
||||
local str, err, partial
|
||||
pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl)
|
||||
remote (string.format ([[
|
||||
data:settimeout(%d)
|
||||
str = string.rep('a', %d)
|
||||
data:send(str)
|
||||
print('server: sleeping for %ds')
|
||||
socket.sleep(%d)
|
||||
print('server: woke up')
|
||||
data:send(str)
|
||||
]], 2*tm, len, sl, sl))
|
||||
data:settimeout(tm)
|
||||
str, err, partial, elapsed = data:receive(2*len)
|
||||
check_timeout(tm, sl, elapsed, err, "receive", "blocking",
|
||||
string.len(str or partial) == 2*len)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_blockingtimeoutsend(len, tm, sl)
|
||||
reconnect()
|
||||
local str, err, total
|
||||
pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl)
|
||||
remote (string.format ([[
|
||||
data:settimeout(%d)
|
||||
str = data:receive(%d)
|
||||
print('server: sleeping for %ds')
|
||||
socket.sleep(%d)
|
||||
print('server: woke up')
|
||||
str = data:receive(%d)
|
||||
]], 2*tm, len, sl, sl, len))
|
||||
data:settimeout(tm)
|
||||
str = string.rep("a", 2*len)
|
||||
total, err, partial, elapsed = data:send(str)
|
||||
check_timeout(tm, sl, elapsed, err, "send", "blocking",
|
||||
total == 2*len)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function empty_connect()
|
||||
reconnect()
|
||||
if data then data:close() data = nil end
|
||||
remote [[
|
||||
if data then data:close() data = nil end
|
||||
data = server:accept()
|
||||
]]
|
||||
data, err = socket.connect("", port)
|
||||
if not data then
|
||||
pass("ok")
|
||||
data = socket.connect(host, port)
|
||||
else
|
||||
pass("gethostbyname returns localhost on empty string...")
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function isclosed(c)
|
||||
return c:getfd() == -1 or c:getfd() == (2^32-1)
|
||||
end
|
||||
|
||||
function active_close()
|
||||
reconnect()
|
||||
if isclosed(data) then fail("should not be closed") end
|
||||
data:close()
|
||||
if not isclosed(data) then fail("should be closed") end
|
||||
data = nil
|
||||
local udp = socket.udp()
|
||||
if isclosed(udp) then fail("should not be closed") end
|
||||
udp:close()
|
||||
if not isclosed(udp) then fail("should be closed") end
|
||||
pass("ok")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_closed()
|
||||
local back, partial, err
|
||||
local str = 'little string'
|
||||
reconnect()
|
||||
pass("trying read detection")
|
||||
remote (string.format ([[
|
||||
data:send('%s')
|
||||
data:close()
|
||||
data = nil
|
||||
]], str))
|
||||
-- try to get a line
|
||||
back, err, partial = data:receive()
|
||||
if not err then fail("should have gotten 'closed'.")
|
||||
elseif err ~= "closed" then fail("got '"..err.."' instead of 'closed'.")
|
||||
elseif str ~= partial then fail("didn't receive partial result.")
|
||||
else pass("graceful 'closed' received") end
|
||||
reconnect()
|
||||
pass("trying write detection")
|
||||
remote [[
|
||||
data:close()
|
||||
data = nil
|
||||
]]
|
||||
total, err, partial = data:send(string.rep("ugauga", 100000))
|
||||
if not err then
|
||||
pass("failed: output buffer is at least %d bytes long!", total)
|
||||
elseif err ~= "closed" then
|
||||
fail("got '"..err.."' instead of 'closed'.")
|
||||
else
|
||||
pass("graceful 'closed' received after %d bytes were sent", partial)
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_selectbugs()
|
||||
local r, s, e = socket.select(nil, nil, 0.1)
|
||||
assert(type(r) == "table" and type(s) == "table" and
|
||||
(e == "timeout" or e == "error"))
|
||||
pass("both nil: ok")
|
||||
local udp = socket.udp()
|
||||
udp:close()
|
||||
r, s, e = socket.select({ udp }, { udp }, 0.1)
|
||||
assert(type(r) == "table" and type(s) == "table" and
|
||||
(e == "timeout" or e == "error"))
|
||||
pass("closed sockets: ok")
|
||||
e = pcall(socket.select, "wrong", 1, 0.1)
|
||||
assert(e == false)
|
||||
e = pcall(socket.select, {}, 1, 0.1)
|
||||
assert(e == false)
|
||||
pass("invalid input: ok")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function accept_timeout()
|
||||
io.stderr:write("accept with timeout (if it hangs, it failed): ")
|
||||
local s, e = socket.bind("*", 0, 0)
|
||||
assert(s, e)
|
||||
local t = socket.gettime()
|
||||
s:settimeout(1)
|
||||
local c, e = s:accept()
|
||||
assert(not c, "should not accept")
|
||||
assert(e == "timeout", string.format("wrong error message (%s)", e))
|
||||
t = socket.gettime() - t
|
||||
assert(t < 2, string.format("took to long to give up (%gs)", t))
|
||||
s:close()
|
||||
pass("good")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function connect_timeout()
|
||||
io.stderr:write("connect with timeout (if it hangs, it failed!): ")
|
||||
local t = socket.gettime()
|
||||
local c, e = socket.tcp()
|
||||
assert(c, e)
|
||||
c:settimeout(0.1)
|
||||
local t = socket.gettime()
|
||||
local r, e = c:connect("10.0.0.1", 81)
|
||||
print(r, e)
|
||||
assert(not r, "should not connect")
|
||||
assert(socket.gettime() - t < 2, "took too long to give up.")
|
||||
c:close()
|
||||
print("ok")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function accept_errors()
|
||||
io.stderr:write("not listening: ")
|
||||
local d, e = socket.bind("*", 0)
|
||||
assert(d, e);
|
||||
local c, e = socket.tcp();
|
||||
assert(c, e);
|
||||
d:setfd(c:getfd())
|
||||
d:settimeout(2)
|
||||
local r, e = d:accept()
|
||||
assert(not r and e)
|
||||
print("ok: ", e)
|
||||
io.stderr:write("not supported: ")
|
||||
local c, e = socket.udp()
|
||||
assert(c, e);
|
||||
d:setfd(c:getfd())
|
||||
local r, e = d:accept()
|
||||
assert(not r and e)
|
||||
print("ok: ", e)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function connect_errors()
|
||||
io.stderr:write("connection refused: ")
|
||||
local c, e = socket.connect("localhost", 1);
|
||||
assert(not c and e)
|
||||
print("ok: ", e)
|
||||
io.stderr:write("host not found: ")
|
||||
local c, e = socket.connect("host.is.invalid", 1);
|
||||
assert(not c and e, e)
|
||||
print("ok: ", e)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function rebind_test()
|
||||
local c = socket.bind("localhost", 0)
|
||||
local i, p = c:getsockname()
|
||||
local s, e = socket.tcp()
|
||||
assert(s, e)
|
||||
s:setoption("reuseaddr", false)
|
||||
r, e = s:bind("localhost", p)
|
||||
assert(not r, "managed to rebind!")
|
||||
assert(e)
|
||||
print("ok: ", e)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function getstats_test()
|
||||
reconnect()
|
||||
local t = 0
|
||||
for i = 1, 25 do
|
||||
local c = math.random(1, 100)
|
||||
remote (string.format ([[
|
||||
str = data:receive(%d)
|
||||
data:send(str)
|
||||
]], c))
|
||||
data:send(string.rep("a", c))
|
||||
data:receive(c)
|
||||
t = t + c
|
||||
local r, s, a = data:getstats()
|
||||
assert(r == t, "received count failed" .. tostring(r)
|
||||
.. "/" .. tostring(t))
|
||||
assert(s == t, "sent count failed" .. tostring(s)
|
||||
.. "/" .. tostring(t))
|
||||
end
|
||||
print("ok")
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_nonblocking(size)
|
||||
reconnect()
|
||||
print("Testing " .. 2*size .. " bytes")
|
||||
remote(string.format([[
|
||||
data:send(string.rep("a", %d))
|
||||
socket.sleep(0.5)
|
||||
data:send(string.rep("b", %d) .. "\n")
|
||||
]], size, size))
|
||||
local err = "timeout"
|
||||
local part = ""
|
||||
local str
|
||||
data:settimeout(0)
|
||||
while 1 do
|
||||
str, err, part = data:receive("*l", part)
|
||||
if err ~= "timeout" then break end
|
||||
end
|
||||
assert(str == (string.rep("a", size) .. string.rep("b", size)))
|
||||
reconnect()
|
||||
remote(string.format([[
|
||||
str = data:receive(%d)
|
||||
socket.sleep(0.5)
|
||||
str = data:receive(2*%d, str)
|
||||
data:send(str)
|
||||
]], size, size))
|
||||
data:settimeout(0)
|
||||
local start = 0
|
||||
while 1 do
|
||||
ret, err, start = data:send(str, start+1)
|
||||
if err ~= "timeout" then break end
|
||||
end
|
||||
data:send("\n")
|
||||
data:settimeout(-1)
|
||||
local back = data:receive(2*size)
|
||||
assert(back == str, "'" .. back .. "' vs '" .. str .. "'")
|
||||
print("ok")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
|
||||
test("method registration")
|
||||
test_methods(socket.tcp(), {
|
||||
"accept",
|
||||
"bind",
|
||||
"close",
|
||||
"connect",
|
||||
"dirty",
|
||||
"getfd",
|
||||
"getpeername",
|
||||
"getsockname",
|
||||
"getstats",
|
||||
"setstats",
|
||||
"listen",
|
||||
"receive",
|
||||
"send",
|
||||
"setfd",
|
||||
"setoption",
|
||||
"setpeername",
|
||||
"setsockname",
|
||||
"settimeout",
|
||||
"shutdown",
|
||||
})
|
||||
|
||||
test_methods(socket.udp(), {
|
||||
"close",
|
||||
"getpeername",
|
||||
"dirty",
|
||||
"getfd",
|
||||
"getpeername",
|
||||
"getsockname",
|
||||
"receive",
|
||||
"receivefrom",
|
||||
"send",
|
||||
"sendto",
|
||||
"setfd",
|
||||
"setoption",
|
||||
"setpeername",
|
||||
"setsockname",
|
||||
"settimeout"
|
||||
})
|
||||
|
||||
test("select function")
|
||||
test_selectbugs()
|
||||
|
||||
test("connect function")
|
||||
connect_timeout()
|
||||
empty_connect()
|
||||
connect_errors()
|
||||
|
||||
test("rebinding: ")
|
||||
rebind_test()
|
||||
|
||||
test("active close: ")
|
||||
active_close()
|
||||
|
||||
test("closed connection detection: ")
|
||||
test_closed()
|
||||
|
||||
test("accept function: ")
|
||||
accept_timeout()
|
||||
accept_errors()
|
||||
|
||||
test("getstats test")
|
||||
getstats_test()
|
||||
|
||||
test("character line")
|
||||
test_asciiline(1)
|
||||
test_asciiline(17)
|
||||
test_asciiline(200)
|
||||
test_asciiline(4091)
|
||||
test_asciiline(80199)
|
||||
test_asciiline(8000000)
|
||||
test_asciiline(80199)
|
||||
test_asciiline(4091)
|
||||
test_asciiline(200)
|
||||
test_asciiline(17)
|
||||
test_asciiline(1)
|
||||
|
||||
test("mixed patterns")
|
||||
test_mixed(1)
|
||||
test_mixed(17)
|
||||
test_mixed(200)
|
||||
test_mixed(4091)
|
||||
test_mixed(801990)
|
||||
test_mixed(4091)
|
||||
test_mixed(200)
|
||||
test_mixed(17)
|
||||
test_mixed(1)
|
||||
|
||||
test("binary line")
|
||||
test_rawline(1)
|
||||
test_rawline(17)
|
||||
test_rawline(200)
|
||||
test_rawline(4091)
|
||||
test_rawline(80199)
|
||||
test_rawline(8000000)
|
||||
test_rawline(80199)
|
||||
test_rawline(4091)
|
||||
test_rawline(200)
|
||||
test_rawline(17)
|
||||
test_rawline(1)
|
||||
|
||||
test("raw transfer")
|
||||
test_raw(1)
|
||||
test_raw(17)
|
||||
test_raw(200)
|
||||
test_raw(4091)
|
||||
test_raw(80199)
|
||||
test_raw(8000000)
|
||||
test_raw(80199)
|
||||
test_raw(4091)
|
||||
test_raw(200)
|
||||
test_raw(17)
|
||||
test_raw(1)
|
||||
|
||||
test("non-blocking transfer")
|
||||
test_nonblocking(1)
|
||||
test_nonblocking(17)
|
||||
test_nonblocking(200)
|
||||
test_nonblocking(4091)
|
||||
test_nonblocking(80199)
|
||||
test_nonblocking(800000)
|
||||
test_nonblocking(80199)
|
||||
test_nonblocking(4091)
|
||||
test_nonblocking(200)
|
||||
test_nonblocking(17)
|
||||
test_nonblocking(1)
|
||||
|
||||
test("total timeout on send")
|
||||
test_totaltimeoutsend(800091, 1, 3)
|
||||
test_totaltimeoutsend(800091, 2, 3)
|
||||
test_totaltimeoutsend(800091, 5, 2)
|
||||
test_totaltimeoutsend(800091, 3, 1)
|
||||
|
||||
test("total timeout on receive")
|
||||
test_totaltimeoutreceive(800091, 1, 3)
|
||||
test_totaltimeoutreceive(800091, 2, 3)
|
||||
test_totaltimeoutreceive(800091, 3, 2)
|
||||
test_totaltimeoutreceive(800091, 3, 1)
|
||||
|
||||
test("blocking timeout on send")
|
||||
test_blockingtimeoutsend(800091, 1, 3)
|
||||
test_blockingtimeoutsend(800091, 2, 3)
|
||||
test_blockingtimeoutsend(800091, 3, 2)
|
||||
test_blockingtimeoutsend(800091, 3, 1)
|
||||
|
||||
test("blocking timeout on receive")
|
||||
test_blockingtimeoutreceive(800091, 1, 3)
|
||||
test_blockingtimeoutreceive(800091, 2, 3)
|
||||
test_blockingtimeoutreceive(800091, 3, 2)
|
||||
test_blockingtimeoutreceive(800091, 3, 1)
|
||||
|
||||
test(string.format("done in %.2fs", socket.gettime() - start))
|
15
etc/tests/luasocket/testsrvr.lua
Normal file
15
etc/tests/luasocket/testsrvr.lua
Normal file
@ -0,0 +1,15 @@
|
||||
socket = require("socket");
|
||||
host = host or "localhost";
|
||||
port = port or "8383";
|
||||
server = assert(socket.bind(host, port));
|
||||
ack = "\n";
|
||||
while 1 do
|
||||
print("server: waiting for client connection...");
|
||||
control = assert(server:accept());
|
||||
while 1 do
|
||||
command = assert(control:receive());
|
||||
assert(control:send(ack));
|
||||
print(command);
|
||||
(loadstring(command))();
|
||||
end
|
||||
end
|
37
etc/tests/luasocket/testsupport.lua
Normal file
37
etc/tests/luasocket/testsupport.lua
Normal file
@ -0,0 +1,37 @@
|
||||
function readfile(name)
|
||||
local f = io.open(name, "rb")
|
||||
if not f then return nil end
|
||||
local s = f:read("*a")
|
||||
f:close()
|
||||
return s
|
||||
end
|
||||
|
||||
function similar(s1, s2)
|
||||
return string.lower(string.gsub(s1 or "", "%s", "")) ==
|
||||
string.lower(string.gsub(s2 or "", "%s", ""))
|
||||
end
|
||||
|
||||
function fail(msg)
|
||||
msg = msg or "failed"
|
||||
error(msg, 2)
|
||||
end
|
||||
|
||||
function compare(input, output)
|
||||
local original = readfile(input)
|
||||
local recovered = readfile(output)
|
||||
if original ~= recovered then fail("comparison failed")
|
||||
else print("ok") end
|
||||
end
|
||||
|
||||
local G = _G
|
||||
local set = rawset
|
||||
local warn = print
|
||||
|
||||
local setglobal = function(table, key, value)
|
||||
warn("changed " .. key)
|
||||
set(table, key, value)
|
||||
end
|
||||
|
||||
setmetatable(G, {
|
||||
__newindex = setglobal
|
||||
})
|
Reference in New Issue
Block a user