You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
335 lines
9.6 KiB
335 lines
9.6 KiB
require("lunit")
|
|
|
|
local network = require("network")
|
|
local serialization = require("serialization")
|
|
local BaseControl = require("bc")
|
|
local Event = BaseControl.Event
|
|
|
|
module("bc-tests", package.seeall, lunit.testcase)
|
|
|
|
-- Basics {{{
|
|
function test_init()
|
|
local bc = BaseControl({test_noun=true}, {test_verb=function() end})
|
|
assert_true(bc:has_noun("test_noun"), "Local nouns were not initialized")
|
|
assert_true(bc:has_verb("test_verb"), "Local verbs were not initialized")
|
|
end
|
|
|
|
function test_local_noun()
|
|
local bc = BaseControl({test_noun2=1234})
|
|
assert_equal(1234, bc:get_noun("test_noun2"), "Invalid initial value")
|
|
bc:set_noun("test_noun2", 4321)
|
|
assert_equal(4321, bc:get_noun("test_noun2"), "Invalid new value")
|
|
end
|
|
|
|
function test_local_verb()
|
|
local bc = BaseControl(nil, {
|
|
test_verb2 = function(_, _, a, b)
|
|
assert_equal(12, a, "Invalid parameter A")
|
|
assert_equal(34, b, "Invalid parameter B")
|
|
end,
|
|
})
|
|
|
|
bc:call_verb("test_verb2", 12, 34)
|
|
end
|
|
|
|
function test_unknown()
|
|
local bc = BaseControl()
|
|
|
|
assert_false(bc:has_noun("unknown"), "has_noun failed")
|
|
assert_equal(nil, bc:get_noun("unknown"), "get_noun failed")
|
|
assert_error("Unknown noun writable", function()
|
|
bc:set_noun("unknown", 1234)
|
|
end)
|
|
end
|
|
-- }}}
|
|
|
|
-- Networking {{{
|
|
function test_hello()
|
|
local bc1 = BaseControl({hello1=true}, {hello1v=function() end})
|
|
local bc2 = BaseControl({hello2=true}, {hello2v=function() end})
|
|
|
|
assert_true(bc1:has_noun("hello1"), "Announcement did not come through")
|
|
assert_true(bc2:has_noun("hello1"), "Announcement did not come through")
|
|
assert_true(bc1:has_noun("hello2"), "Announcement did not come through")
|
|
assert_true(bc2:has_noun("hello2"), "Announcement did not come through")
|
|
|
|
assert_true(bc1:has_verb("hello1v"), "Anverbcement did not come through")
|
|
assert_true(bc2:has_verb("hello1v"), "Anverbcement did not come through")
|
|
assert_true(bc1:has_verb("hello2v"), "Anverbcement did not come through")
|
|
assert_true(bc2:has_verb("hello2v"), "Anverbcement did not come through")
|
|
end
|
|
|
|
function test_remote_noun()
|
|
local a = {n = "A", bc = BaseControl({noun1=1234}), addr = network.get_scene()}
|
|
local b = {n = "B", bc = BaseControl({noun2=4321}), addr = network.get_scene()}
|
|
local c = {n = "C", bc = BaseControl(), addr = network.get_scene()}
|
|
local abc = {a, b, c, a, c}
|
|
|
|
for _, bc in ipairs(abc) do
|
|
network.set_scene(bc.addr)
|
|
assert_equal(1234, bc.bc:get_noun("noun1"), bc.n..": noun1 failed!")
|
|
assert_equal(4321, bc.bc:get_noun("noun2"), bc.n..": noun2 failed!")
|
|
end
|
|
end
|
|
|
|
function test_noun_nv()
|
|
local bc1 = BaseControl({noun_nv=1234})
|
|
local addr1 = network.get_scene()
|
|
local bc2 = BaseControl()
|
|
local addr2 = network.get_scene()
|
|
|
|
assert_equal(1234, bc2:get_noun("noun_nv"), "Wrong answer!")
|
|
network.set_scene(addr1)
|
|
bc1:set_noun("noun_nv", 4321)
|
|
network.set_scene(addr2)
|
|
assert_equal(4321, bc2:get_noun("noun_nv"), "Wrong answer!")
|
|
end
|
|
|
|
function test_remote_verb()
|
|
local tmp_a = 1
|
|
local tmp_b = 64
|
|
local a = {n = "A", bc = BaseControl(), addr = network.get_scene()}
|
|
local b = {n = "B", bc = BaseControl(nil, {verb1 = function(_, _, a, b)
|
|
assert_equal(tmp_a, a, "A is wrong!")
|
|
assert_equal(tmp_b, b, "B is wrong!")
|
|
end}), addr = network.get_scene()}
|
|
local c = {n = "C", bc = BaseControl(), addr = network.get_scene()}
|
|
local abc = {b, a, b, c, a, c}
|
|
|
|
for _, bc in ipairs(abc) do
|
|
network.set_scene(bc.addr)
|
|
bc.bc:call_verb("verb1", tmp_a, tmp_b)
|
|
tmp_a = tmp_a + 1
|
|
tmp_b = tmp_b + 1
|
|
end
|
|
end
|
|
|
|
function test_two_way_verb()
|
|
local bc1 = BaseControl(nil, {twoway1 = function(bc, _, verb, par)
|
|
bc:call_verb(verb, par * 2)
|
|
end})
|
|
local addr1 = network.get_scene()
|
|
|
|
local result
|
|
local bc2 = BaseControl(nil, {twoway2 = function(bc, _, res)
|
|
result = res
|
|
end})
|
|
local addr2 = network.get_scene()
|
|
|
|
bc2:call_verb("twoway1", "twoway2", 1234)
|
|
assert_equal(2468, result, "Double call failed")
|
|
end
|
|
-- }}}
|
|
|
|
-- Listening {{{
|
|
function test_listen_attach()
|
|
local bc1 = BaseControl({listen1=4321})
|
|
local addr1 = network.get_scene()
|
|
local bc2 = BaseControl()
|
|
|
|
local tmp
|
|
local tmp2
|
|
|
|
local id = bc2:listen("listen1", Event.Change, function(newval)
|
|
if tmp == nil then
|
|
fail("Should not have been called")
|
|
end
|
|
assert_equal(tmp, newval, "Change not correct")
|
|
tmp2 = newval
|
|
end)
|
|
|
|
network.set_scene(addr1)
|
|
for _, t in ipairs{1, 2, 3, 4} do
|
|
tmp = t
|
|
bc1:set_noun("listen1", t)
|
|
assert_equal(t, tmp2, "Listener not called")
|
|
end
|
|
|
|
bc2:cancel(id)
|
|
|
|
bc1:set_noun("listen1", 1234)
|
|
end
|
|
|
|
function test_listen_modes()
|
|
local bc1 = BaseControl({listen2=4321})
|
|
local addr1 = network.get_scene()
|
|
local bc2 = BaseControl()
|
|
local addr2 = network.get_scene()
|
|
|
|
local values = {
|
|
{e=Event.Change, p=nil, s=1234, snot=1234, s2=1235},
|
|
{e=Event.Rising, p=nil, s=1236, snot=1233, s2=1237},
|
|
{e=Event.Falling, p=nil, s=1236, snot=1237, s2=1235},
|
|
{e=Event.Equals, p=1337, s=1337, snot=1234, s2=1337},
|
|
{e=Event.Above, p=4321, s=4333, snot=1234, s2=4334},
|
|
{e=Event.Below, p=4321, s=1234, snot=4444, s2=1212},
|
|
}
|
|
|
|
for _, test in ipairs(values) do
|
|
local active = false
|
|
local fired = false
|
|
network.set_scene(addr2)
|
|
local id = bc2:listen("listen2", test.e, test.p, function(new)
|
|
if not active then
|
|
fail("Should not have been called")
|
|
end
|
|
assert_equal(test.s, new, "Wrong value!")
|
|
fired = true
|
|
end)
|
|
|
|
network.set_scene(addr1)
|
|
active = true
|
|
bc1:set_noun("listen2", test.s)
|
|
assert_true(fired, "Listener was not called")
|
|
|
|
fired = false
|
|
bc1:set_noun("listen2", test.snot)
|
|
assert_false(fired, "Listener was accidentally called")
|
|
|
|
network.set_scene(addr2)
|
|
active = false
|
|
bc2:cancel(id)
|
|
|
|
network.set_scene(addr1)
|
|
bc1:set_noun("listen2", test.s2)
|
|
end
|
|
end
|
|
-- }}}
|
|
|
|
-- Dirty Business {{{
|
|
function test_connectivity_loss_listening()
|
|
local bc1 = BaseControl({connectivity2=12345})
|
|
local addr1 = network.get_scene()
|
|
local bc2 = BaseControl()
|
|
local addr2 = network.get_scene()
|
|
|
|
local called = 0
|
|
local id = bc2:listen("connectivity2", Event.Change, nil, function()
|
|
called = called + 1
|
|
end)
|
|
|
|
network.set_scene(addr1)
|
|
bc1:set_noun("connectivity2", 321)
|
|
assert_equal(1, called, "Listener was not called!")
|
|
|
|
network.deregister(addr2)
|
|
|
|
network.allow_blackhole = true
|
|
do
|
|
bc1:set_noun("connectivity2", 123)
|
|
assert_equal(1, called, "Listener was called?!")
|
|
|
|
local bc2 = BaseControl()
|
|
local addr2 = network.get_scene()
|
|
|
|
local called2 = false
|
|
local id2 = bc2:listen("connectivity2", Event.Change, nil, function()
|
|
called2 = true
|
|
end)
|
|
|
|
network.set_scene(addr1)
|
|
bc1:set_noun("connectivity2", 321)
|
|
assert_true(called2, "Listener was not called!")
|
|
assert_equal(1, called, "Original listener was called?!")
|
|
end
|
|
network.allow_blackhole = false
|
|
end
|
|
|
|
function test_cleanup()
|
|
local bc1 = BaseControl({cleanup1=1234})
|
|
local addr1 = network.get_scene()
|
|
local bc2 = BaseControl()
|
|
local addr2 = network.get_scene()
|
|
|
|
assert_true(bc2:has_noun("cleanup1"), "Setup failed")
|
|
assert_equal(1234, bc2:get_noun("cleanup1"), "Setup failed")
|
|
|
|
network.set_scene(addr1)
|
|
bc1:cleanup()
|
|
|
|
network.set_scene(addr2)
|
|
assert_equal(nil, bc2:get_noun("cleanup1"), "Cleanup failed")
|
|
assert_false(bc2:has_noun("cleanup1"), "Cleanup failed")
|
|
end
|
|
|
|
function test_connectivity_loss()
|
|
local bc1 = BaseControl({connectivity=4433})
|
|
local addr1 = network.get_scene()
|
|
local bc2 = BaseControl()
|
|
local addr2 = network.get_scene()
|
|
|
|
assert_true(bc2:has_noun("connectivity"), "Setup failed")
|
|
assert_equal(4433, bc2:get_noun("connectivity"), "Setup failed")
|
|
|
|
network.deregister(addr1)
|
|
|
|
network.allow_blackhole = true
|
|
assert_true(bc2:has_noun("connectivity"), "Test error")
|
|
assert_equal(nil, bc2:get_noun("connectivity"), "Invalid response from offline node")
|
|
network.allow_blackhole = false
|
|
|
|
-- Come back online
|
|
local bc1 = BaseControl({connectivity=4432})
|
|
network.set_scene(addr2)
|
|
assert_true(bc2:has_noun("connectivity"), "Reconnect failed")
|
|
assert_equal(4432, bc2:get_noun("connectivity"), "Reconnect failed")
|
|
end
|
|
|
|
function test_isolation()
|
|
local bc_outside = BaseControl({isolation1=4321})
|
|
local bc1 = BaseControl({isolation2=1234}, nil, {
|
|
port=1234,
|
|
})
|
|
local bc2 = BaseControl(nil, nil, {
|
|
port=1234,
|
|
})
|
|
|
|
assert_equal(nil, bc2:get_noun("isolation1"), "Leak!")
|
|
assert_equal(1234, bc2:get_noun("isolation2"), "Port failure")
|
|
end
|
|
|
|
function test_malicious_messages()
|
|
local bc1 = BaseControl({malicious=1234})
|
|
local addr1 = network.get_scene()
|
|
local bc2 = BaseControl({malicious2=4321})
|
|
local addr2 = network.get_scene()
|
|
|
|
network.send(addr1, bc1.port, serialization.serialize{
|
|
ty=7, -- LISTEN_REQUEST
|
|
noun="unknown", event=Event.Change, id="dead-beef",
|
|
})
|
|
network.send(addr1, bc1.port, serialization.serialize{
|
|
ty=8, -- LISTEN_NOTIFY
|
|
id="dead-beef", value=1234567,
|
|
})
|
|
network.send(addr1, bc1.port, serialization.serialize{
|
|
ty=9, -- LISTEN_CANCEL
|
|
noun="unknown", id="dead-beef",
|
|
})
|
|
|
|
assert_equal(1234, bc2:get_noun("malicious"))
|
|
end
|
|
|
|
function test_malicious_broadcast()
|
|
local bc1 = BaseControl({malicious3=1234})
|
|
local addr1 = network.get_scene()
|
|
local bc2 = BaseControl()
|
|
local addr2 = network.get_scene()
|
|
local bc3 = BaseControl()
|
|
local addr3 = network.get_scene()
|
|
|
|
network.broadcast(bc1.port, serialization.serialize{
|
|
ty=2, -- ANNOUNCE
|
|
nouns={"malicious3"}, verbs={},
|
|
})
|
|
|
|
-- bc1 can't be fooled, as it owns this noun
|
|
network.set_scene(addr1)
|
|
assert_equal(1234, bc1:get_noun("malicious3"), "Injection successful")
|
|
|
|
-- bc2 unfortunately can be fooled and must be
|
|
network.set_scene(addr2)
|
|
assert_equal(nil, bc2:get_noun("malicious3"), "Injection failed")
|
|
end
|
|
-- }}}
|