luby/crates/lb/tests/net.lua
2025-06-30 20:11:54 +10:00

185 lines
6.0 KiB
Lua

local ok, net = pcall(require, "lb:net")
if not ok then return end
describe("ipaddr", function()
test("invalid ipaddr throws", function()
assert(not pcall(net.ipaddr, "invalid ip"))
end)
test("comparison", function()
local a = net.ipaddr("10.0.0.1")
local b = net.ipaddr("10.0.0.1")
local c = net.ipaddr("10.0.0.2")
assert(a ~= nil and a ~= {} and a ~= "10.0.0.1" and a ~= 167772161)
assert(a == a and a == b and a ~= c and b ~= c and c == c and c ~= a)
assert(a <= b and a < c and a <= c and b < c and b <= c and a <= a and c <= c)
assert(not (a < b or a > b or a > c or b > c or a >= c or b >= c))
end)
test("tostring", function()
local ip = net.ipaddr("10.0.0.1")
assert(tostring(ip) == "10.0.0.1")
end)
end)
describe("tcp", function()
describe("socket", function()
test("bind", function()
local socket = net.bind_tcp("127.0.0.1")
-- binds to the correct port
assert(tostring(socket:local_addr():ip()) == "127.0.0.1")
assert(socket:local_addr():port() ~= 0)
-- should not be able to rebind socket
assert(not pcall(socket.bind, socket, net.socketaddr("127.0.0.1")))
end)
test("options", function()
local socket = net.tcp()
-- keepalive
socket:set_keepalive(true)
assert(socket:keepalive() == true)
socket:set_keepalive(false)
assert(socket:keepalive() == false)
-- reuseaddr
socket:set_reuseaddr(true)
assert(socket:reuseaddr() == true)
socket:set_reuseaddr(false)
assert(socket:reuseaddr() == false)
-- reuseport not always supported on all platforms
-- sendbuf
socket:set_sendbuf(4096)
assert(socket:sendbuf() >= 4096)
assert(not pcall(socket.set_sendbuf, socket, 0))
assert(not pcall(socket.set_sendbuf, socket, -1))
-- recvbuf
socket:set_recvbuf(4096)
assert(socket:recvbuf() >= 4096)
assert(not pcall(socket.set_recvbuf, socket, 0))
assert(not pcall(socket.set_recvbuf, socket, -1))
-- linger
socket:set_linger(0)
assert(socket:linger() == 0)
socket:set_linger(2)
assert(math.abs(socket:linger() - 2) < 0.1)
socket:set_linger(-1)
assert(socket:linger() == 0)
-- nodelay
socket:set_nodelay(true)
assert(socket:nodelay() == true)
socket:set_nodelay(false)
assert(socket:nodelay() == false)
end)
test("can't use socket after conversion", function()
local socket = net.tcp()
socket:bind(net.socketaddr("127.0.0.1"))
socket:listen(10) -- convert to listener
assert(not pcall(socket.listen, socket, 10)) -- socket consumed
assert(not pcall(socket.local_addr, socket))
end)
end)
describe("stream", function()
test("no concurrent two reads/writes", function()
local listener = net.listen_tcp(net.localhost())
local client = net.connect_tcp(listener:local_addr())
local server = listener()
local reader = spawn(function()
assert(client:read(1) == nil) -- this should block first, then return nil from disconnection
end)
spawn(function()
assert(not pcall(client.read, client, 1)) -- this should fail, since the first task is still reading
end):await()
server:close()
reader:await()
end)
test("allow concurrent read/write", function()
local listener = net.listen_tcp(net.localhost())
local client = net.connect_tcp(listener:local_addr())
local server = listener()
local reader = spawn(function()
assert(client:read(1) == nil) -- this should block first, then return nil from disconnection
end)
spawn(function()
client:write("hello") -- should be able to write while the first task is reading
end):await()
server:close()
reader:await()
end)
test("stop reading from disconnected stream", function()
local listener = net.listen_tcp(net.localhost())
local client = net.connect_tcp(listener:local_addr())
local server = listener()
local reader = spawn(function()
while client:read(4) ~= nil do
end
assert(client:try_read(4) == nil)
assert(client:read_partial(4) == nil)
assert(client:read(4) == nil)
end)
for _ = 1, 10 do
assert(server:write("ping") == true)
end
sleep(100)
server:close()
reader:await()
end)
test("stop writing to disconnected stream", function()
local listener = net.listen_tcp(net.localhost())
local client = net.connect_tcp(listener:local_addr())
local server = listener()
local writer = spawn(function()
while client:write("pong") do
end
assert(client:try_write("pong") == nil)
assert(client:write_partial("pong") == nil)
assert(client:write("pong") == false)
end)
for _ = 1, 10 do
assert(server:read(4) == "pong")
end
sleep(100)
server:close()
writer:await()
end)
end)
describe("listener", function()
test("accept", function()
local listener = net.listen_tcp(net.localhost())
local addr = listener:local_addr()
local accepted = false
local client = net.tcp()
local accepted_stream
listener:on_accept(function(stream)
accepted = true
accepted_stream = stream
-- configure stream
stream:set_nodelay(true)
assert(stream:nodelay() == true)
end)
-- connect client
local client_stream = client:connect(addr)
local server_stream = listener()
assert(accepted)
assert(accepted_stream ~= nil)
-- check addresses
assert(server_stream:local_addr() ~= nil)
assert(server_stream:peer_addr() ~= nil)
assert(client_stream:local_addr() ~= nil)
assert(client_stream:peer_addr() ~= nil)
-- test data transfer
server_stream:write("hello")
local buf = client_stream:read(5)
assert(buf ~= nil and #buf == 5)
assert(buf == "hello")
-- close
server_stream:close()
client_stream:close()
end)
end)
end)