Skip to content

Instantly share code, notes, and snippets.

@azdle
Created November 2, 2022 02:40
Show Gist options
  • Save azdle/7e8362250b1d97a18877e009f22a8d15 to your computer and use it in GitHub Desktop.
Save azdle/7e8362250b1d97a18877e009f22a8d15 to your computer and use it in GitHub Desktop.
Testing Packing and Unpacking in Lua
--
-- Note: run with `busted packunpackit.lua`
--
local havecosock, cosock = pcall(require, "cosock")
local socket = require "socket"
local pack = table and table.pack or pack
local unpack = table and table.unpack or unpack
local function mvpack(...)
return {...}
end
local function manpack(...)
local args = {...}
local t = {}
for i = 1,10 do
t[i] = args[i]
end
return t
end
local function unpacker(t)
return unpack(t)
end
local function passthrough(f, ...)
local ret = {f(...)}
return unpack(ret)
end
function reter(foo, err)
if err then
return nil,2,3,4,5
else
return true
end
end
function unit(...)
return ...
end
local transform = {
output = function(a, b, c, d, e)
return nil, b, c, d, e
end
}
local function wrappedtransform(...)
local input = {...}
local ret = {unit(unpack(input))}
return unpack(ret)
end
test("packing", function()
local t = table.pack(1,2,3,4,5)
assert.same(#t, 5)
assert.same(#table.pack(reter(nil, true)), 5)
assert.same(#{reter(nil, true)}, 5)
end)
test("unpacking nonnil", function()
local t = {1,2,3,4,5}
local t2 = {unpacker(t)}
assert.same(t, t2)
end)
test("unpacking nilprefix", function()
local t = {nil,2,3,4,5}
local t2 = {passthrough(unpacker, t)}
assert.same(t, t2)
end)
test("unpacking midnil", function()
local t = {1,2,nil,4,5}
local t2 = {passthrough(unpacker, t)}
assert.same(t, t2)
end)
test("mvunpacking nonnil", function()
local t = mvpack(1,2,3,4,5)
local t2 = {passthrough(unpacker, t)}
assert.same(t, t2)
end)
test("mvunpacking nilprefix", function()
local t = mvpack(nil,2,3,4,5)
local t2 = {passthrough(unpacker, t)}
assert.same(t, t2)
end)
test("mvunpacking midnil", function()
local t = mvpack(1,2,nil,4,5)
local t2 = {passthrough(unpacker, t)}
assert.same(t, t2)
end)
test("fn unpacking", function()
local t = mvpack(nil,2,3,4,5)
local t2 = {passthrough(reter, nil, true)}
assert.same(t, t2)
end)
test("manpacked unpacking", function()
local t = manpack(nil,2,3,4,5)
local t2 = {passthrough(reter, nil, true)}
assert.same(t, t2)
end)
test("output unpacking", function()
local a, b, c, d, e = transform.output(1,2,3,4,5)
assert.same({a,b,c,d,e}, {nil, 2,3,4,5})
end)
test("wrapped transform unpacking", function()
local a, b, c, d, e = wrappedtransform(1,2,3,4,5)
assert.same({a,b,c,d,e}, {1, 2,3,4,5})
local a, b, c, d, e = wrappedtransform(nil,2,3,4,5)
assert.same({a,b,c,d,e}, {nil,2,3,4,5})
end)
--[[
test("raw pack", function()
local t = {}
t[1] = nil
t[2] = "foo"
assert.same({nil, "foo"}, {unpack(t)})
end)
]]
test("unmessed", function()
local t = {nil, true, true}
assert.same({nil, true, true}, {unpack(t)})
end)
test("just looking", function()
local t = {nil, true, true}
local status = t[1]
local err = t[2]
local ret2 = {transform.output(unpack(t))}
local status2, err2 = unit(unpack(ret2))
assert(status == nil)
assert(err == true)
if err then
assert.same({nil, true, true}, {unpack(t)})
else
error("wrong way")
end
end)
--[[
test("manual messing", function()
local t = {nil, true}
t[3] = true
assert.same({nil, true, true}, {unpack(t)})
end)
]]--
test("manual re-messing", function()
local t = {nil, true, true}
t[3] = true
assert.same({nil, true, true}, {unpack(t)})
end)
--[[
test("packed manual messing", function()
local t = table.pack(nil, true)
t[3] = true
assert.same({nil, true, true}, {unpack(t)})
end)
]]
test("packed manual re-messing", function()
local t = table.pack(nil, true, true)
t[3] = true
assert.same({nil, true, true}, {unpack(t)})
end)
if havecosock then
test("cosock", function()
cosock.reset()
cosock.spawn(function()
local ret = {cosock.socket.select(nil, nil, 0)} -- force a yield
assert.same({nil, nil, "timeout"}, ret)
assert(#{nil, nil, "timeout"}, #ret)
assert.same({nil, nil, "timeout"}, {unpack(ret)})
assert(#{nil, nil, "timeout"} == #{unpack(ret)})
end)
cosock.run()
end)
end
test("luasocket", function()
local ret = {socket.select(nil, nil, 0)}
assert.same({{}, {}, "timeout"}, ret)
assert(#{{}, {}, "timeout"}, #ret)
assert.same({{}, {}, "timeout"}, {unpack(ret)})
assert(#{{}, {}, "timeout"} == #{unpack(ret)})
end)
test("actual socket", function()
function thing()
local sock = socket.udp()
assert(sock:setsockname("localhost", 0))
assert(sock:settimeout(0))
local ret = {sock["receivefrom"](sock, unpack({}))}
local status = ret[1]
local err = ret[2]
if not status and err then
assert(2 == #ret)
assert.same({nil, "timeout"}, ret)
assert(2 == #{unpack(ret)})
assert.same({nil, "timeout"}, {unpack(ret)})
return unpack(ret)
end
end
local status, err = thing()
assert(status == nil)
assert(err == "timeout")
end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment