Switch from lunit to u-test

lunit is unmaintained since ~2011.  Switch to u-test [1] instead which
seems to be more actively maintained.

[1]: https://github.com/IUdalov/u-test
This commit is contained in:
rahix 2021-01-29 22:11:16 +01:00
parent 0d852d7aac
commit 4a5349be96
20 changed files with 701 additions and 1335 deletions

View file

@ -1,188 +0,0 @@
require("lunit")
local serialization = require("serialization")
local BaseControl = require("bc")
module("local", package.seeall, lunit.testcase)
function test_construct()
local function is_a_bc(bc)
assert_true(bc.local_nouns ~= nil)
assert_true(bc.local_verbs ~= nil)
end
-- Short init
is_a_bc(BaseControl())
is_a_bc(BaseControl:new())
is_a_bc(BaseControl:finalize())
is_a_bc(BaseControl:finalize({}, 10))
is_a_bc(BaseControl:finalize({}))
-- Long init
local bc = BaseControl:new()
bc:finalize()
is_a_bc(bc)
local bc = BaseControl:new()
bc:finalize({}, 10)
is_a_bc(bc)
local bc = BaseControl:new()
bc:finalize({})
is_a_bc(bc)
end
function test_register()
local bc = BaseControl:new()
bc:register("register1", 1234)
bc:finalize()
-- Register after finalizing
local bc = BaseControl:finalize()
assert_error_match("after finalizing", function()
bc:register("register2", 4321)
end)
-- Register exisiting
local bc = BaseControl:new()
bc:register("register3", 123)
assert_error_match("already registered", function()
bc:register("register3", 12)
end)
end
function test_register_batch()
local bc = BaseControl:new()
bc:register{
rb1=1234,
rb2=4321,
rb3v=function() end,
}
bc:finalize()
assert_true(bc:has_noun("rb1"))
assert_true(bc:has_noun("rb2"))
assert_true(bc:has_verb("rb3v"))
end
function test_available()
local bc = BaseControl:new()
bc:register("available1", 1234)
bc:register("available2v", function() end)
bc:finalize()
assert_equal(1234, bc.local_nouns["available1"])
assert_true(bc.local_verbs["available2v"] ~= nil)
end
function test_get()
local bc = BaseControl:new()
bc:register("get1", 1234)
bc:register("get2v", function() end)
bc:finalize()
assert_equal(1234, bc:get("get1"), "wrong value for noun")
assert_error_match("unknown", function()
bc:get("get2")
end)
assert_error_match("not a noun", function()
bc:get("get2v")
end)
end
function test_set()
local bc = BaseControl:new()
bc:register("set1", 31415)
bc:register("set2v", function() end)
bc:finalize()
assert_equal(31415, bc:get("set1"), "wrong value for noun")
bc:set("set1", 14142)
assert_equal(14142, bc:get("set1"), "wrong value for noun")
assert_error_match("not a local", function()
bc:set("set2", 12345)
end)
assert_error_match("can't be cast into a noun", function()
bc:set("set2v", 12345)
end)
assert_pass(function()
bc:set("set2v", function() end)
end)
assert_error_match("can't be cast into a verb", function()
bc:set("set1", function() end)
end)
end
function test_has_iter_nouns()
local bc = BaseControl:new(
BaseControl.Network(31213) -- Network isolation
)
bc:register("hin1", 123)
bc:register("hin2v", function() end)
bc:register("hin3", 321)
bc:finalize()
assert_true(bc:has_noun("hin1"), "exisiting noun not found")
assert_false(bc:has_noun("hin2"), "non-existing noun found")
assert_false(bc:has_noun("hin2v"), "verb found as noun")
assert_true(bc:has_noun("hin3"), "exisiting noun not found")
local nouns = bc:nouns()
table.sort(nouns)
assert_equal(2, #nouns, "noun-list incorrect")
assert_equal("hin1", nouns[1], "noun-list incorrect")
assert_equal("hin3", nouns[2], "noun-list incorrect")
end
function test_call_verb()
local bc = BaseControl:new()
local flag1, flag2 = 0, 0
bc:register("call1", function(a, b)
flag1 = a + b
flag2 = flag2 + 1
end)
bc:finalize()
bc:call("call1", 1, 2)
assert_equal(3, flag1, "call failed")
assert_equal(1, flag2, "call failed")
bc:call("call1", 10, 10)
assert_equal(20, flag1, "call failed")
assert_equal(2, flag2, "call failed")
end
function test_has_iter_verbs()
local bc = BaseControl:new(
BaseControl.Network(31214) -- Network isolation
)
bc:register("hiv1v", function() end)
bc:register("hiv2", 123)
bc:register("hiv3v", function() end)
bc:finalize()
assert_true(bc:has_verb("hiv1v"), "exisiting verb not found")
assert_false(bc:has_verb("hiv2v"), "non-existing verb found")
assert_false(bc:has_verb("hiv2"), "noun found as verb")
assert_true(bc:has_verb("hiv3v"), "exisiting verb not found")
local verbs = bc:verbs()
table.sort(verbs)
assert_equal(2, #verbs, "verb-list incorrect")
assert_equal("hiv1v", verbs[1], "verb-list incorrect")
assert_equal("hiv3v", verbs[2], "verb-list incorrect")
end
function test_iter_empty()
local bc = BaseControl:new(
BaseControl.Network(31211) -- Network isolation
):finalize()
assert_equal(31211, bc.network.port, "wrong port")
assert_equal(0, #bc:nouns(), "nouns found in empty network")
assert_equal(0, #bc:verbs(), "verbs found in empty network")
end

View file

@ -1,77 +0,0 @@
require("lunit")
local network = require("network")
local serialization = require("serialization")
local BaseControl = require("bc")
module("network", package.seeall, lunit.testcase)
function test_multinode()
local bc1 = BaseControl:finalize()
local bc2 = BaseControl:new()
bc2:register("multinode1", 123)
bc2:register("multinode2v", function() end)
bc2:finalize()
local bc3 = BaseControl:finalize()
assert_true(bc1:has_noun("multinode1"), "d1: remote noun missing")
assert_true(bc1:has_verb("multinode2v"), "d1: remote verb missing")
assert_true(bc3:has_noun("multinode1"), "d2: remote noun missing")
assert_true(bc3:has_verb("multinode2v"), "d2: remote verb missing")
end
function test_get_network()
local bc1 = BaseControl:new()
bc1:register("getnw1", 123)
bc1:finalize()
local bc2 = BaseControl:new()
assert_equal(123, bc2:get("getnw1"), "wrong value")
assert_error_match("unknown", function()
bc2:unknown("getnw2")
end)
end
function test_call_network()
local bc1 = BaseControl:new()
local tmp, n = 0, 0
bc1:register("callnw1", function(param, p2)
assert_equal(p2, 1234)
tmp = param
n = n + 1
end)
bc1:finalize()
local bc2 = BaseControl:new()
bc2:call("callnw1", 4321, 1234)
assert_equal(4321, tmp, "call incomplete")
assert_equal(1, n, "call not correct")
end
function test_call_sync()
local bc1 = BaseControl:new()
local n = 0
bc1:register("sync1", function(p1, p2)
assert_equal(p2, 12)
n = n + 1
return p1 + 10, "hello"
end)
bc1:finalize()
-- Test locally
assert_true(bc1:call("sync1", 20, 12), "call not true")
local ret, val = bc1:call_sync("sync1", 30, 12)
assert_equal(40, ret, "local sync not correct")
assert_equal("hello", val, "local sync not multiple")
assert_equal(2, n, "wrong invokation number")
-- Test remote
local bc2 = BaseControl:new()
assert_true(bc2:call("sync1", 20, 12), "call not true")
local ret, val = bc2:call_sync("sync1", 30, 12)
assert_equal(40, ret, "local sync not correct")
assert_equal("hello", val, "local sync not multiple")
assert_equal(4, n, "wrong invokation number")
end

22
tests/run.lua Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env lua5.2
-- Insert necessary directories into lua search path
package.path = "./?.lua;./tests/?.lua;./tests/support/?.lua;"..package.path
local test = require("u-test")
test_sources = {
"tests/cleanup.lua",
"tests/dirty.lua",
"tests/iters.lua",
"tests/listening.lua",
"tests/local.lua",
"tests/network.lua",
"tests/timeout.lua",
}
for _, source in ipairs(test_sources) do
loadfile("./tests/"..source)()
end
test.result()
test.summary()

View file

@ -0,0 +1,23 @@
local network = require("network")
local modem = {}
function modem.open(port)
-- Nothing
end
function modem.send(addr, port, msg)
network.send(addr, port, msg)
end
function modem.close(port)
-- Nothing
end
function modem.broadcast(port, msg)
network.broadcast(port, msg)
end
return {
modem = modem,
}

View file

@ -0,0 +1,10 @@
local socket = require("socket")
local computer = {}
local start = socket.gettime()
function computer.uptime()
return socket.gettime() - start
end
return computer

39
tests/support/event.lua Normal file
View file

@ -0,0 +1,39 @@
local network = require("network")
local component = require("component")
local event = {}
local addr_num = 0
function event.listen(event, callback)
if event ~= "modem_message" then
error("Event '"..event"' is not supported!")
end
addr = "A"..addr_num
addr_num = addr_num + 1
function ev_callback(ev, local_addr, ...)
-- Inject local address so the check passes
component.modem.address = local_addr
callback(ev, local_addr, ...)
end
network.register(addr, ev_callback)
end
function event.ignore(event, callback)
if event ~= "modem_message" then
error("Event '"..event"' is not supported!")
end
network.deregister(network.get_scene())
end
function event.pullFiltered(timeout, filter)
while true do
local msg = table.pack(network.pull())
if msg[1] == nil then
return nil
elseif filter(table.unpack(msg)) then
return table.unpack(msg)
end
end
end
return event

113
tests/support/network.lua Normal file
View file

@ -0,0 +1,113 @@
local network = {
allow_blackhole = false,
}
local nodes = {}
local active_node = {}
local latest_message = {}
local inject_message = {}
function network.register(addr, callback)
if nodes[addr] ~= nil then
error("Address "..addr.." already registered!")
end
nodes[addr] = callback
active_node = {}
table.insert(active_node, addr)
end
function network.deregister(addr)
nodes[addr] = nil
end
function network.get_callback(addr)
return nodes[addr]
end
function network.send(addr, port, msg)
local callback = nodes[addr]
if callback == nil then
if not network.allow_blackhole then
error("Send message to offline node: "..tostring(addr))
end
return nil
end
local current_node = active_node[#active_node]
-- Push target onto node-stack
table.insert(active_node, addr)
-- print("Sending from "..current_node.." to "..addr..": "..msg)
-- print(require("inspect").inspect(active_node))
latest_message[addr] = {
from=current_node,
port=port,
msg=msg,
}
callback("modem_message", addr, current_node, port, 0, msg)
-- Remove again
active_node[#active_node] = nil
end
function network.broadcast(port, msg)
local current_node = active_node[#active_node]
-- print("Broadcasting from "..current_node)
for addr in pairs(nodes) do
if addr ~= current_node then
network.send(addr, port, msg)
end
end
end
function network.pull()
local current_node = active_node[#active_node]
if inject_message[current_node] ~= nil and #inject_message[current_node] > 0 then
local message = inject_message[current_node][1]
table.remove(inject_message[current_node], 1)
-- Actually send the injected message now
-- but save the last latest_message
local latest = latest_message[current_node]
table.insert(active_node, message.from)
network.send(current_node, message.port, message.msg)
active_node[#active_node] = nil
latest_message[current_node] = latest
return "modem_message", current_node, message.from, message.port, 0, message.msg
end
if latest_message[current_node] == nil then
return nil
end
local message = latest_message[current_node]
-- Delete message
latest_message[current_node] = nil
return "modem_message", current_node, message.from, message.port, 0, message.msg
end
function network.set_scene(addr)
active_node = {}
table.insert(active_node, addr)
end
function network.get_scene(addr)
return active_node[#active_node]
end
function network.inject(addr, from, port, msg)
if inject_message[addr] == nil then
inject_message[addr] = {}
end
table.insert(inject_message[addr], {
from=from,
port=port,
msg=msg,
})
end
return network

View file

@ -0,0 +1,140 @@
local serialization = {}
-- delay loaded tables fail to deserialize cross [C] boundaries (such as when having to read files that cause yields)
local local_pairs = function(tbl)
local mt = getmetatable(tbl)
return (mt and mt.__pairs or pairs)(tbl)
end
-- Important: pretty formatting will allow presenting non-serializable values
-- but may generate output that cannot be unserialized back.
function serialization.serialize(value, pretty)
local kw = {["and"]=true, ["break"]=true, ["do"]=true, ["else"]=true,
["elseif"]=true, ["end"]=true, ["false"]=true, ["for"]=true,
["function"]=true, ["goto"]=true, ["if"]=true, ["in"]=true,
["local"]=true, ["nil"]=true, ["not"]=true, ["or"]=true,
["repeat"]=true, ["return"]=true, ["then"]=true, ["true"]=true,
["until"]=true, ["while"]=true}
local id = "^[%a_][%w_]*$"
local ts = {}
local function s(v, l)
local t = type(v)
if t == "nil" then
return "nil"
elseif t == "boolean" then
return v and "true" or "false"
elseif t == "number" then
if v ~= v then
return "0/0"
elseif v == math.huge then
return "math.huge"
elseif v == -math.huge then
return "-math.huge"
else
return tostring(v)
end
elseif t == "string" then
return string.format("%q", v):gsub("\\\n","\\n")
elseif t == "table" and pretty and getmetatable(v) and getmetatable(v).__tostring then
return tostring(v)
elseif t == "table" then
if ts[v] then
if pretty then
return "recursion"
else
error("tables with cycles are not supported")
end
end
ts[v] = true
local i, r = 1, nil
local f
if pretty then
local ks, sks, oks = {}, {}, {}
for k in local_pairs(v) do
if type(k) == "number" then
table.insert(ks, k)
elseif type(k) == "string" then
table.insert(sks, k)
else
table.insert(oks, k)
end
end
table.sort(ks)
table.sort(sks)
for _, k in ipairs(sks) do
table.insert(ks, k)
end
for _, k in ipairs(oks) do
table.insert(ks, k)
end
local n = 0
f = table.pack(function()
n = n + 1
local k = ks[n]
if k ~= nil then
return k, v[k]
else
return nil
end
end)
else
f = table.pack(local_pairs(v))
end
for k, v in table.unpack(f) do
if r then
r = r .. "," .. (pretty and ("\n" .. string.rep(" ", l)) or "")
else
r = "{"
end
local tk = type(k)
if tk == "number" and k == i then
i = i + 1
r = r .. s(v, l + 1)
else
if tk == "string" and not kw[k] and string.match(k, id) then
r = r .. k
else
r = r .. "[" .. s(k, l + 1) .. "]"
end
r = r .. "=" .. s(v, l + 1)
end
end
ts[v] = nil -- allow writing same table more than once
return (r or "{") .. "}"
else
if pretty then
return tostring(v)
else
error("unsupported type: " .. t)
end
end
end
local result = s(value, 1)
local limit = type(pretty) == "number" and pretty or 10
if pretty then
local truncate = 0
while limit > 0 and truncate do
truncate = string.find(result, "\n", truncate + 1, true)
limit = limit - 1
end
if truncate then
return result:sub(1, truncate) .. "..."
end
end
return result
end
function serialization.unserialize(data)
-- checkArg(1, data, "string")
local result, reason = load("return " .. data, "=data", _, {math={huge=math.huge}})
if not result then
return nil, reason
end
local ok, output = pcall(result)
if not ok then
return nil, output
end
return output
end
return serialization

30
tests/support/uuid.lua Normal file
View file

@ -0,0 +1,30 @@
local bit32 = require("bit32")
local uuid = {}
function uuid.next()
-- e.g. 3c44c8a9-0613-46a2-ad33-97b6ba2e9d9a
-- 8-4-4-4-12 (halved sizes because bytes make hex pairs)
local sets = {4, 2, 2, 2, 6}
local result = ""
local pos = 0
for _,set in ipairs(sets) do
if result:len() > 0 then
result = result .. "-"
end
for _ = 1,set do
local byte = math.random(0, 255)
if pos == 6 then
byte = bit32.bor(bit32.band(byte, 0x0F), 0x40)
elseif pos == 8 then
byte = bit32.bor(bit32.band(byte, 0x3F), 0x80)
end
result = result .. string.format("%02x", byte)
pos = pos + 1
end
end
return result
end
return uuid

View file

@ -1,27 +1,25 @@
require("lunit")
local test = require("u-test")
local network = require("network")
local serialization = require("serialization")
local BaseControl = require("bc")
module("cleanup", package.seeall, lunit.testcase)
function test_clean_simple()
function test.clean_simple()
local bc = BaseControl:new()
bc:close()
local bc = BaseControl:finalize()
assert_true(network.get_callback(addr) ~= nil, "callback not registered")
test.is_true(network.get_callback(addr) ~= nil, "callback not registered")
bc:close()
assert_error(function()
test.error_raised(function()
bc:nouns()
end)
assert_nil(network.get_callback(addr), "callback still in network")
test.is_nil(network.get_callback(addr), "callback still in network")
end
function test_clean_network()
function test.clean_network()
local bc1 = BaseControl:new()
local addr1 = network.get_scene()
bc1:register("cln1", 123)
@ -31,18 +29,18 @@ function test_clean_network()
local bc2 = BaseControl:new()
local addr2 = network.get_scene()
assert_true(bc2:has_noun("cln1"), "init failed")
assert_true(bc2:has_verb("cln2v"), "init failed")
test.is_true(bc2:has_noun("cln1"), "init failed")
test.is_true(bc2:has_verb("cln2v"), "init failed")
network.set_scene(addr1)
bc1:close()
network.set_scene(addr2)
assert_false(bc2:has_noun("cln1"), "close failed")
assert_false(bc2:has_verb("cln2v"), "close failed")
test.is_false(bc2:has_noun("cln1"), "close failed")
test.is_false(bc2:has_verb("cln2v"), "close failed")
end
function test_clean_network2()
function test.clean_network2()
local bc1 = BaseControl:new()
local addr1 = network.get_scene()
local n = 0
@ -55,22 +53,22 @@ function test_clean_network2()
local bc2 = BaseControl:new()
local addr2 = network.get_scene()
assert_equal(0, n, "verb called too much/little")
assert_true(bc2:call("cln4v"), "verb not called")
assert_equal(1, n, "verb called too much/little")
assert_equal(1231, bc2:get("cln3"), "noun not retrieved correctly")
test.equal(0, n, "verb called too much/little")
test.is_true(bc2:call("cln4v"), "verb not called")
test.equal(1, n, "verb called too much/little")
test.equal(1231, bc2:get("cln3"), "noun not retrieved correctly")
network.set_scene(addr1)
bc1:close()
assert_false(bc2:call("cln4v"), "verb called")
assert_equal(1, n, "verb called too much/little")
assert_error_match("unknown", function()
test.is_false(bc2:call("cln4v"), "verb called")
test.equal(1, n, "verb called too much/little")
test.error_raised(function()
bc2:get("cln3")
end)
end, "unknown")
end
function test_unclean_deregister()
function test.unclean_deregister()
local bc = BaseControl:new()
local addr = network.get_scene()
@ -81,7 +79,7 @@ function test_unclean_deregister()
serialization.serialize{ty=BaseControl.Message.Hello}
)
assert_true(network.get_callback(addr) ~= nil, "callback not registered")
test.is_true(network.get_callback(addr) ~= nil, "callback not registered")
bc = nil
collectgarbage()
network.send(
@ -89,5 +87,5 @@ function test_unclean_deregister()
BaseControl.Network.default_port,
serialization.serialize{ty=BaseControl.Message.Hello}
)
assert_nil(network.get_callback(addr), "callback still in network")
test.is_nil(network.get_callback(addr), "callback still in network")
end

View file

@ -1,12 +1,10 @@
require("lunit")
local test = require("u-test")
local network = require("network")
local serialization = require("serialization")
local BaseControl = require("bc")
module("dirty", package.seeall, lunit.testcase)
function test_get_network_robust()
function test.get_network_robust()
local bc1 = BaseControl:new()
bc1:register("getrob1", 123)
bc1:finalize()
@ -25,18 +23,18 @@ function test_get_network_robust()
}
)
assert_equal(123, bc2:get("getrob1"), "wrong value")
assert_error_match("unknown", function()
test.equal(123, bc2:get("getrob1"), "wrong value")
test.error_raised(function()
bc2:get("getrob2")
end)
end, "unknown")
end
function test_call_sync_network_robust()
function test.call_sync_network_robust()
local bc1 = BaseControl:new()
local addr1 = network.get_scene()
local n = 0
bc1:register("syncr1", function(p1, p2)
assert_equal(p2, 12)
test.equal(p2, 12)
n = n + 1
return p1 + 10, "hello"
end)
@ -45,7 +43,7 @@ function test_call_sync_network_robust()
local bc2 = BaseControl:new()
local addr2 = network.get_scene()
assert_true(bc2:call("syncr1", 20, 12), "call not true")
test.is_true(bc2:call("syncr1", 20, 12), "call not true")
network.inject(
addr2,
@ -59,12 +57,12 @@ function test_call_sync_network_robust()
)
local ret, val = bc2:call_sync("syncr1", 30, 12)
assert_equal(40, ret, "local sync not correct")
assert_equal("hello", val, "local sync not multiple")
assert_equal(2, n, "wrong invokation number")
test.equal(40, ret, "local sync not correct")
test.equal("hello", val, "local sync not multiple")
test.equal(2, n, "wrong invokation number")
end
function test_finalize_robust()
function test.finalize_robust()
local bc1 = BaseControl:new()
bc1:register("finaln1", 123)
bc1:finalize()
@ -104,7 +102,7 @@ function test_finalize_robust()
bc2:finalize{"finaln1", "finaln2", "finaln3"}
assert_true(bc2:has_noun("finaln1"), "noun missing")
assert_true(bc2:has_noun("finaln2"), "noun missing")
assert_true(bc2:has_noun("finaln3"), "noun missing")
test.is_true(bc2:has_noun("finaln1"), "noun missing")
test.is_true(bc2:has_noun("finaln2"), "noun missing")
test.is_true(bc2:has_noun("finaln3"), "noun missing")
end

View file

@ -1,12 +1,10 @@
require("lunit")
local test = require("u-test")
local network = require("network")
local serialization = require("serialization")
local BaseControl = require("bc")
module("iters", package.seeall, lunit.testcase)
function test_multinode_iters()
function test.multinode_iters()
local bc1 = BaseControl:new(
BaseControl.Network(121233)
)
@ -23,13 +21,13 @@ function test_multinode_iters()
local nouns = bc2:nouns()
table.sort(nouns)
assert_equal(2, #nouns, "noun-list incorrect")
assert_equal("miter1", nouns[1], "noun-list incorrect")
assert_equal("miter3", nouns[2], "noun-list incorrect")
test.equal(2, #nouns, "noun-list incorrect")
test.equal("miter1", nouns[1], "noun-list incorrect")
test.equal("miter3", nouns[2], "noun-list incorrect")
local verbs = bc2:verbs()
table.sort(verbs)
assert_equal(2, #verbs, "verb-list incorrect")
assert_equal("miter2v", verbs[1], "verb-list incorrect")
assert_equal("miter4v", verbs[2], "verb-list incorrect")
test.equal(2, #verbs, "verb-list incorrect")
test.equal("miter2v", verbs[1], "verb-list incorrect")
test.equal("miter4v", verbs[2], "verb-list incorrect")
end

View file

@ -1,12 +1,10 @@
require("lunit")
local test = require("u-test")
local network = require("network")
local serialization = require("serialization")
local BaseControl = require("bc")
module("listening", package.seeall, lunit.testcase)
function test_invalid_query()
function test.invalid_query()
local bc = BaseControl:new()
local invalids = {
bc.Query.Equals,
@ -15,13 +13,13 @@ function test_invalid_query()
}
for _, q in ipairs(invalids) do
assert_error_match("invalid", function()
test.error_raised(function()
bc:listen("invq1", q, function() end)
end)
end, "invalid")
end
end
function test_listen_simple()
function test.listen_simple()
local bc = BaseControl:new()
bc:register("lisimpl1", 1234)
bc:finalize()
@ -31,14 +29,14 @@ function test_listen_simple()
n = n + 1
end)
assert_equal(0, n, "wrong number of listener invokations")
test.equal(0, n, "wrong number of listener invokations")
bc:set("lisimpl1", 4321)
assert_equal(1, n, "wrong number of listener invokations")
test.equal(1, n, "wrong number of listener invokations")
bc:set("lisimpl1", 42)
assert_equal(2, n, "wrong number of listener invokations")
test.equal(2, n, "wrong number of listener invokations")
end
function test_listen_network_simple()
function test.listen_network_simple()
local bc1 = BaseControl:new()
local addr1 = network.get_scene()
bc1:register("lin1", 1234)
@ -49,19 +47,19 @@ function test_listen_network_simple()
local tmp, n = 0, 0
bc2:listen("lin1", bc1.Query.Change, function(new)
assert_equal(tmp, new, "value did not propagate")
test.equal(tmp, new, "value did not propagate")
n = n + 1
end)
network.set_scene(addr1)
tmp = 12
assert_equal(0, n, "wrong number of listener invokations")
test.equal(0, n, "wrong number of listener invokations")
bc1:set("lin1", 12)
assert_equal(1, n, "wrong number of listener invokations")
test.equal(1, n, "wrong number of listener invokations")
tmp = 16
bc1:set("lin1", 16)
assert_equal(2, n, "wrong number of listener invokations")
test.equal(2, n, "wrong number of listener invokations")
end
-- Generate testcases for queries
@ -75,35 +73,35 @@ do
{name="below", query=BaseControl.Query.Below(100), pos1=12, neg=124, pos2=23},
}
for _, test in ipairs(tests) do
for _, test_info in ipairs(tests) do
-- Local test
listening["test_listen_query_"..test.name] = function()
test["listen_query_"..test_info.name] = function()
local bc = BaseControl:new()
local noun = "lq"..test.name.."1"
local noun = "lq"..test_info.name.."1"
bc:register(noun, 0)
bc:finalize()
local n = 0
bc:listen(noun, test.query, function(new)
bc:listen(noun, test_info.query, function(new)
n = n + 1
end)
assert_equal(0, n, "wrong number of listener invokations")
bc:set(noun, test.pos1)
assert_equal(1, n, "wrong number of listener invokations")
bc:set(noun, test.neg)
assert_equal(1, n, "wrong number of listener invokations")
bc:set(noun, test.pos2)
assert_equal(2, n, "wrong number of listener invokations")
test.equal(0, n, "wrong number of listener invokations")
bc:set(noun, test_info.pos1)
test.equal(1, n, "wrong number of listener invokations")
bc:set(noun, test_info.neg)
test.equal(1, n, "wrong number of listener invokations")
bc:set(noun, test_info.pos2)
test.equal(2, n, "wrong number of listener invokations")
bc:close()
end
-- Remote test
listening["test_listen_network_query_"..test.name] = function()
test["listen_network_query_"..test_info.name] = function()
local bc1 = BaseControl:new()
local addr1 = network.get_scene()
local noun = "lnq"..test.name.."1"
local noun = "lnq"..test_info.name.."1"
bc1:register(noun, 0)
bc1:finalize()
@ -111,22 +109,22 @@ do
local addr2 = network.get_scene()
local tmp, n = 0, 0
bc2:listen(noun, test.query, function(new)
assert_equal(tmp, new, "value did not propagate")
bc2:listen(noun, test_info.query, function(new)
test.equal(tmp, new, "value did not propagate")
n = n + 1
end)
network.set_scene(addr1)
assert_equal(0, n, "wrong number of listener invokations")
tmp = test.pos1
bc1:set(noun, test.pos1)
assert_equal(1, n, "wrong number of listener invokations")
tmp = test.neg
bc1:set(noun, test.neg)
assert_equal(1, n, "wrong number of listener invokations")
tmp = test.pos2
bc1:set(noun, test.pos2)
assert_equal(2, n, "wrong number of listener invokations")
test.equal(0, n, "wrong number of listener invokations")
tmp = test_info.pos1
bc1:set(noun, test_info.pos1)
test.equal(1, n, "wrong number of listener invokations")
tmp = test_info.neg
bc1:set(noun, test_info.neg)
test.equal(1, n, "wrong number of listener invokations")
tmp = test_info.pos2
bc1:set(noun, test_info.pos2)
test.equal(2, n, "wrong number of listener invokations")
bc1:close()
network.set_scene(addr2)
@ -135,7 +133,7 @@ do
end
end
function test_listen_cancel()
function test.listen_cancel()
local bc = BaseControl:new()
bc:register("lcan1", 123)
bc:finalize()
@ -146,26 +144,26 @@ function test_listen_cancel()
end)
assert_equal(0, n, "wrong number of listener invokations")
test.equal(0, n, "wrong number of listener invokations")
bc:set("lcan1", 321)
assert_equal(1, n, "wrong number of listener invokations")
test.equal(1, n, "wrong number of listener invokations")
-- Cancel the listener
bc:cancel("lcan1", id)
bc:set("lcan1", 12)
assert_equal(1, n, "wrong number of listener invokations")
test.equal(1, n, "wrong number of listener invokations")
assert_error_match("unknown", function()
test.error_raised(function()
bc:cancel("lcan1", id)
end)
end, "unknown")
assert_error_match("unknown", function()
test.error_raised(function()
bc:cancel("lcan2", "fooid")
end)
end, "unknown")
end
function test_listen_cancel_remote()
function test.listen_cancel_remote()
local bc1 = BaseControl:new()
local addr1 = network.get_scene()
bc1:register("lcanr1", 123)
@ -178,12 +176,12 @@ function test_listen_cancel_remote()
local id, ok = bc2:listen("lcanr1", BaseControl.Query.Change, function()
n = n + 1
end)
assert_true(ok, "failed installing")
test.is_true(ok, "failed installing")
network.set_scene(addr1)
assert_equal(0, n, "wrong number of listener invokations")
test.equal(0, n, "wrong number of listener invokations")
bc1:set("lcanr1", 34)
assert_equal(1, n, "wrong number of listener invokations")
test.equal(1, n, "wrong number of listener invokations")
-- Dirty hack to get the test working
local save = bc2.listeners["lcanr1"][id]
@ -193,10 +191,10 @@ function test_listen_cancel_remote()
network.set_scene(addr1)
bc1:set("lcanr1", 21)
assert_equal(1, n, "wrong number of listener invokations")
test.equal(1, n, "wrong number of listener invokations")
end
function test_listen_late_install()
function test.listen_late_install()
local bc1 = BaseControl:new()
local addr1 = network.get_scene()
@ -210,7 +208,7 @@ function test_listen_late_install()
bc2:register("late1", 1234)
bc2:finalize()
assert_equal(0, n, "wrong number of listener invokations")
test.equal(0, n, "wrong number of listener invokations")
bc2:set("late1", 34)
assert_equal(1, n, "wrong number of listener invokations")
test.equal(1, n, "wrong number of listener invokations")
end

184
tests/tests/local.lua Normal file
View file

@ -0,0 +1,184 @@
local test = require("u-test")
local serialization = require("serialization")
local BaseControl = require("bc")
function test.construct()
local function is_a_bc(bc)
test.is_true(bc.local_nouns ~= nil)
test.is_true(bc.local_verbs ~= nil)
end
-- Short init
is_a_bc(BaseControl())
is_a_bc(BaseControl:new())
is_a_bc(BaseControl:finalize())
is_a_bc(BaseControl:finalize({}, 10))
is_a_bc(BaseControl:finalize({}))
-- Long init
local bc = BaseControl:new()
bc:finalize()
is_a_bc(bc)
local bc = BaseControl:new()
bc:finalize({}, 10)
is_a_bc(bc)
local bc = BaseControl:new()
bc:finalize({})
is_a_bc(bc)
end
function test.register()
local bc = BaseControl:new()
bc:register("register1", 1234)
bc:finalize()
-- Register after finalizing
local bc = BaseControl:finalize()
test.error_raised(function()
bc:register("register2", 4321)
end, "after finalizing")
-- Register exisiting
local bc = BaseControl:new()
bc:register("register3", 123)
test.error_raised(function()
bc:register("register3", 12)
end, "already registered")
end
function test.register_batch()
local bc = BaseControl:new()
bc:register{
rb1=1234,
rb2=4321,
rb3v=function() end,
}
bc:finalize()
test.is_true(bc:has_noun("rb1"))
test.is_true(bc:has_noun("rb2"))
test.is_true(bc:has_verb("rb3v"))
end
function test.available()
local bc = BaseControl:new()
bc:register("available1", 1234)
bc:register("available2v", function() end)
bc:finalize()
test.equal(1234, bc.local_nouns["available1"])
test.is_true(bc.local_verbs["available2v"] ~= nil)
end
function test.get()
local bc = BaseControl:new()
bc:register("get1", 1234)
bc:register("get2v", function() end)
bc:finalize()
test.equal(1234, bc:get("get1"), "wrong value for noun")
test.error_raised(function()
bc:get("get2")
end, "unknown")
test.error_raised(function()
bc:get("get2v")
end, "not a noun")
end
function test.set()
local bc = BaseControl:new()
bc:register("set1", 31415)
bc:register("set2v", function() end)
bc:finalize()
test.equal(31415, bc:get("set1"), "wrong value for noun")
bc:set("set1", 14142)
test.equal(14142, bc:get("set1"), "wrong value for noun")
test.error_raised(function()
bc:set("set2", 12345)
end, "not a local")
test.error_raised(function()
bc:set("set2v", 12345)
end, "can't be cast into a noun")
bc:set("set2v", function() end)
test.error_raised(function()
bc:set("set1", function() end)
end, "can't be cast into a verb")
end
function test.has_iter_nouns()
local bc = BaseControl:new(
BaseControl.Network(31213) -- Network isolation
)
bc:register("hin1", 123)
bc:register("hin2v", function() end)
bc:register("hin3", 321)
bc:finalize()
test.is_true(bc:has_noun("hin1"), "exisiting noun not found")
test.is_false(bc:has_noun("hin2"), "non-existing noun found")
test.is_false(bc:has_noun("hin2v"), "verb found as noun")
test.is_true(bc:has_noun("hin3"), "exisiting noun not found")
local nouns = bc:nouns()
table.sort(nouns)
test.equal(2, #nouns, "noun-list incorrect")
test.equal("hin1", nouns[1], "noun-list incorrect")
test.equal("hin3", nouns[2], "noun-list incorrect")
end
function test.call_verb()
local bc = BaseControl:new()
local flag1, flag2 = 0, 0
bc:register("call1", function(a, b)
flag1 = a + b
flag2 = flag2 + 1
end)
bc:finalize()
bc:call("call1", 1, 2)
test.equal(3, flag1, "call failed")
test.equal(1, flag2, "call failed")
bc:call("call1", 10, 10)
test.equal(20, flag1, "call failed")
test.equal(2, flag2, "call failed")
end
function test.has_iter_verbs()
local bc = BaseControl:new(
BaseControl.Network(31214) -- Network isolation
)
bc:register("hiv1v", function() end)
bc:register("hiv2", 123)
bc:register("hiv3v", function() end)
bc:finalize()
test.is_true(bc:has_verb("hiv1v"), "exisiting verb not found")
test.is_false(bc:has_verb("hiv2v"), "non-existing verb found")
test.is_false(bc:has_verb("hiv2"), "noun found as verb")
test.is_true(bc:has_verb("hiv3v"), "exisiting verb not found")
local verbs = bc:verbs()
table.sort(verbs)
test.equal(2, #verbs, "verb-list incorrect")
test.equal("hiv1v", verbs[1], "verb-list incorrect")
test.equal("hiv3v", verbs[2], "verb-list incorrect")
end
function test.iter_empty()
local bc = BaseControl:new(
BaseControl.Network(31211) -- Network isolation
):finalize()
test.equal(31211, bc.network.port, "wrong port")
test.equal(0, #bc:nouns(), "nouns found in empty network")
test.equal(0, #bc:verbs(), "verbs found in empty network")
end

75
tests/tests/network.lua Normal file
View file

@ -0,0 +1,75 @@
local test = require("u-test")
local network = require("network")
local serialization = require("serialization")
local BaseControl = require("bc")
function test.multinode()
local bc1 = BaseControl:finalize()
local bc2 = BaseControl:new()
bc2:register("multinode1", 123)
bc2:register("multinode2v", function() end)
bc2:finalize()
local bc3 = BaseControl:finalize()
test.is_true(bc1:has_noun("multinode1"), "d1: remote noun missing")
test.is_true(bc1:has_verb("multinode2v"), "d1: remote verb missing")
test.is_true(bc3:has_noun("multinode1"), "d2: remote noun missing")
test.is_true(bc3:has_verb("multinode2v"), "d2: remote verb missing")
end
function test.get_network()
local bc1 = BaseControl:new()
bc1:register("getnw1", 123)
bc1:finalize()
local bc2 = BaseControl:new()
test.equal(123, bc2:get("getnw1"), "wrong value")
test.error_raised(function()
bc2:unknown("getnw2")
end, "unknown")
end
function test.call_network()
local bc1 = BaseControl:new()
local tmp, n = 0, 0
bc1:register("callnw1", function(param, p2)
test.equal(p2, 1234)
tmp = param
n = n + 1
end)
bc1:finalize()
local bc2 = BaseControl:new()
bc2:call("callnw1", 4321, 1234)
test.equal(4321, tmp, "call incomplete")
test.equal(1, n, "call not correct")
end
function test.call_sync()
local bc1 = BaseControl:new()
local n = 0
bc1:register("sync1", function(p1, p2)
test.equal(p2, 12)
n = n + 1
return p1 + 10, "hello"
end)
bc1:finalize()
-- Test locally
test.is_true(bc1:call("sync1", 20, 12), "call not true")
local ret, val = bc1:call_sync("sync1", 30, 12)
test.equal(40, ret, "local sync not correct")
test.equal("hello", val, "local sync not multiple")
test.equal(2, n, "wrong invokation number")
-- Test remote
local bc2 = BaseControl:new()
test.is_true(bc2:call("sync1", 20, 12), "call not true")
local ret, val = bc2:call_sync("sync1", 30, 12)
test.equal(40, ret, "local sync not correct")
test.equal("hello", val, "local sync not multiple")
test.equal(4, n, "wrong invokation number")
end

View file

@ -1,12 +1,10 @@
require("lunit")
local test = require("u-test")
local network = require("network")
local serialization = require("serialization")
local BaseControl = require("bc")
module("timeout", package.seeall, lunit.testcase)
function test_timeout_get()
function test.timeout_get()
local bc = BaseControl:new()
local addr = network.get_scene()
@ -22,12 +20,12 @@ function test_timeout_get()
}
)
assert_error_match("timeout", function()
test.error_raised(function()
bc:get("tog1", 0.1)
end)
end, "timeout")
end
function test_timeout_call()
function test.timeout_call()
local bc = BaseControl:new()
local addr = network.get_scene()
@ -42,15 +40,15 @@ function test_timeout_call()
}
)
assert_error_match("timeout", function()
test.error_raised(function()
bc:call_sync(0.1, "toc1v")
end)
end, "timeout")
end
function test_timeout_finalize()
function test.timeout_finalize()
local bc1 = BaseControl:new()
local addr1 = network.get_scene()
assert_error_match("timeout", function()
test.error_raised(function()
bc1:finalize({"to_final1"}, 0.1)
end)
end, "timeout")
end

311
tests/u-test.lua Normal file
View file

@ -0,0 +1,311 @@
-- COMMAND LINE ----------------------------------------------------------------
local function print_help()
print "Usage: target.lua [options] [regex]"
print "\t-h show this message"
print "\t-q quiet mode"
print "\t-s disable colours"
end
local quiet, grey, test_regex
if arg then
for i = 1, #arg do
if arg[i] == "-h" then
print_help()
os.exit(0)
elseif arg[i] == "-q" then
quiet = true
elseif arg[i] == "-s" then
grey = true
elseif not test_regex then
test_regex = arg[i]
else
print_help()
os.exit(1)
end
end
end
-- UTILS -----------------------------------------------------------------------
local function red(str) return grey and str or "\27[1;31m" .. str .. "\27[0m" end
local function blue(str) return grey and str or "\27[1;34m" .. str .. "\27[0m" end
local function green(str) return grey and str or "\27[1;32m" .. str .. "\27[0m" end
local function yellow(str) return grey and str or "\27[1;33m" .. str .. "\27[0m" end
local tab_tag = blue "[----------]"
local done_tag = blue "[==========]"
local run_tag = blue "[ RUN ]"
local ok_tag = green "[ OK ]"
local fail_tag = red "[ FAIL]"
local disabled_tag = yellow "[ DISABLED ]"
local passed_tag = green "[ PASSED ]"
local failed_tag = red "[ FAILED ]"
local ntests = 0
local failed = false
local failed_list = {}
local function trace(start_frame)
print "Trace:"
local frame = start_frame
while true do
local info = debug.getinfo(frame, "Sl")
if not info then break end
if info.what == "C" then
print(frame - start_frame, "??????")
else
print(frame - start_frame, info.short_src .. ":" .. info.currentline .. " ")
end
frame = frame + 1
end
end
local function log(msg)
if not quiet then
print(msg)
end
end
local function fail(msg, start_frame)
failed = true
print("Fail: " .. msg)
trace(start_frame or 4)
end
local function stringize_var_arg(...)
local args = { n = select("#", ...), ... }
local result = {}
for i = 1, args.n do
if type(args[i]) == 'string' then
result[i] = '"' .. tostring(args[i]) .. '"'
else
result[i] = tostring(args[i])
end
end
return table.concat(result, ", ")
end
local function test_pretty_name(suite_name, test_name)
if suite_name == "__root" then
return test_name
else
return suite_name .. "." .. test_name
end
end
-- PUBLIC API -----------------------------------------------------------------
local api = { test_suite_name = "__root", skip = false }
api.assert = function (cond)
if not cond then
fail("assertion " .. tostring(cond) .. " failed")
end
end
api.equal = function (l, r)
if l ~= r then
fail(tostring(l) .. " ~= " .. tostring(r))
end
end
api.not_equal = function (l, r)
if l == r then
fail(tostring(l) .. " == " .. tostring(r))
end
end
api.almost_equal = function (l, r, diff)
if require("math").abs(l - r) > diff then
fail("|" .. tostring(l) .. " - " .. tostring(r) .."| > " .. tostring(diff))
end
end
api.is_false = function (maybe_false)
if maybe_false or type(maybe_false) ~= "boolean" then
fail("got " .. tostring(maybe_false) .. " instead of false")
end
end
api.is_true = function (maybe_true)
if not maybe_true or type(maybe_true) ~= "boolean" then
fail("got " .. tostring(maybe_true) .. " instead of true")
end
end
api.is_not_nil = function (maybe_not_nil)
if type(maybe_not_nil) == "nil" then
fail("got nil")
end
end
api.error_raised = function (f, error_message, ...)
local status, err = pcall(f, ...)
if status == true then
fail("error not raised")
else
if error_message ~= nil then
-- we set "plain" to true to avoid pattern matching in string.find
if err:find(error_message, 1, true) == nil then
fail("'" .. error_message .. "' not found in error '" .. tostring(err) .. "'")
end
end
end
end
api.register_assert = function(assert_name, assert_func)
rawset(api, assert_name, function(...)
local result, msg = assert_func(...)
if not result then
msg = msg or "Assertion "..assert_name.." failed"
fail(msg)
end
end)
end
local function make_type_checker(typename)
api["is_" .. typename] = function (maybe_type)
if type(maybe_type) ~= typename then
fail("got " .. tostring(maybe_type) .. " instead of " .. typename, 4)
end
end
end
local supported_types = {"nil", "boolean", "string", "number", "userdata", "table", "function", "thread"}
for i, supported_type in ipairs(supported_types) do
make_type_checker(supported_type)
end
local last_test_suite
local function run_test(test_suite, test_name, test_function, ...)
local suite_name = test_suite.test_suite_name
local full_test_name = test_pretty_name(suite_name, test_name)
if test_regex and not string.match(full_test_name, test_regex) then
return
end
if test_suite.skip then
log(disabled_tag .. " " .. full_test_name)
return
end
if suite_name ~= last_test_suite then
log(tab_tag)
last_test_suite = suite_name
end
ntests = ntests + 1
failed = false
log(run_tag .. " " .. full_test_name)
local start = os.time()
local status, err
for _, f in ipairs({test_suite.start_up, test_function, test_suite.tear_down}) do
status, err = pcall(f, ...)
if not status then
failed = true
print(tostring(err))
end
end
local stop = os.time()
local is_test_failed = not status or failed
log(string.format("%s %s %d sec",
is_test_failed and fail_tag or ok_tag,
full_test_name,
os.difftime(stop, start)))
if is_test_failed then
table.insert(failed_list, full_test_name)
end
end
api.summary = function ()
log(done_tag)
local nfailed = #failed_list
if nfailed == 0 then
log(passed_tag .. " " .. ntests .. " test(s)")
os.exit(0)
else
log(failed_tag .. " " .. nfailed .. " out of " .. ntests .. ":")
for _, test_name in ipairs(failed_list) do
log(failed_tag .. "\t" .. test_name)
end
os.exit(1)
end
end
api.result = function ( ... )
return ntests, #failed_list
end
local default_start_up = function () end
local default_tear_down = function () collectgarbage() end
api.start_up = default_start_up
api.tear_down = default_tear_down
local all_test_cases = { __root = {} }
local function handle_new_test(suite, test_name, test_function)
local suite_name = suite.test_suite_name
if not all_test_cases[suite_name] then
all_test_cases[suite_name] = {}
end
all_test_cases[suite_name][test_name] = test_function
local info = debug.getinfo(test_function)
if info.nparams == nil and
string.sub(test_name, #test_name - 1, #test_name) ~= "_p"
or info.nparams == 0 then
run_test(suite, test_name, test_function)
end
end
local function lookup_test_with_params(suite, test_name)
local suite_name = suite.test_suite_name
if all_test_cases[suite_name] and all_test_cases[suite_name][test_name] then
return function (...)
run_test(suite
, test_name .. "(" .. stringize_var_arg(...) .. ")"
, all_test_cases[suite_name][test_name], ...)
end
else
local full_test_name = test_pretty_name(suite_name, test_name)
table.insert(failed_list, full_test_name)
ntests = ntests + 1
log(fail_tag .. " No " .. full_test_name .. " parametrized test case!")
end
end
local function new_test_suite(_, name)
local test_suite = {
test_suite_name = name,
start_up = default_start_up,
tear_down = default_tear_down,
skip = false }
setmetatable(test_suite, {
__newindex = handle_new_test,
__index = lookup_test_with_params })
return test_suite
end
local test_suites = {}
setmetatable(api, {
__index = function (tbl, name)
if all_test_cases.__root[name] then
return lookup_test_with_params(tbl, name)
end
if not test_suites[name] then
test_suites[name] = new_test_suite(tbl, name)
end
return test_suites[name]
end,
__newindex = handle_new_test
})
return api