Add automated tests for some mods (#605)

Depends on mineunit from https://github.com/S-S-X/mineunit

mesecons, mesecons_mvps, mesecons_fpga, and mesecons_luacontroller are now tested.
This commit is contained in:
Jude Melton-Houghton
2022-12-06 11:54:21 -05:00
committed by GitHub
parent 2ede29df9c
commit c10ce2dbc5
21 changed files with 1593 additions and 0 deletions

156
.test_fixtures/mesecons.lua Normal file
View File

@ -0,0 +1,156 @@
mineunit("core")
mineunit("server")
mineunit("voxelmanip")
mineunit:set_current_modname("mesecons")
mineunit:set_modpath("mesecons", "../mesecons")
sourcefile("../mesecons/init")
-- Utility node: this conductor is used to test the connectivity and state of adjacent wires.
do
local off_spec = {conductor = {
state = mesecon.state.off,
rules = mesecon.rules.alldirs,
onstate = "mesecons:test_conductor_on",
}}
local on_spec = {conductor = {
state = mesecon.state.on,
rules = mesecon.rules.alldirs,
offstate = "mesecons:test_conductor_off",
}}
mesecon.register_node("mesecons:test_conductor", {
description = "Test Conductor",
}, {mesecons = off_spec}, {mesecons = on_spec})
end
-- Utility node: this receptor is used to test power sources.
do
local off_spec = {receptor = {
state = mesecon.state.off,
rules = mesecon.rules.alldirs,
}}
local on_spec = {receptor = {
state = mesecon.state.on,
rules = mesecon.rules.alldirs,
}}
mesecon.register_node("mesecons:test_receptor", {
description = "Test Receptor",
}, {mesecons = off_spec}, {mesecons = on_spec})
end
-- Utility node: this effector is used to test circuit outputs.
do
-- This is a list of actions in the form {<kind>, <pos>},
-- where <kind> is "on", "off", or "overheat".
mesecon._test_effector_events = {}
local function action_on(pos, node)
table.insert(mesecon._test_effector_events, {"on", pos})
node.param2 = node.param2 % 64 + 128 -- Turn on bit 7
minetest.swap_node(pos, node)
end
local function action_off(pos, node)
table.insert(mesecon._test_effector_events, {"off", pos})
node.param2 = node.param2 % 64 -- Turn off bit 7
minetest.swap_node(pos, node)
end
local function action_change(pos, node, rule_name, new_state)
if mesecon.do_overheat(pos) then
table.insert(mesecon._test_effector_events, {"overheat", pos})
minetest.remove_node(pos)
return
end
-- Set the value of a bit in param2 according to the rule name and new state.
local bit = tonumber(rule_name.name, 2)
local bits_above = node.param2 - node.param2 % (bit * 2)
local bits_below = node.param2 % bit
local bits_flipped = new_state == mesecon.state.on and bit or 0
node.param2 = bits_above + bits_flipped + bits_below
minetest.swap_node(pos, node)
end
minetest.register_node("mesecons:test_effector", {
description = "Test Effector",
mesecons = {effector = {
action_on = action_on,
action_off = action_off,
action_change = action_change,
rules = {
{x = 1, y = 0, z = 0, name = "000001"},
{x = -1, y = 0, z = 0, name = "000010"},
{x = 0, y = 1, z = 0, name = "000100"},
{x = 0, y = -1, z = 0, name = "001000"},
{x = 0, y = 0, z = 1, name = "010000"},
{x = 0, y = 0, z = -1, name = "100000"},
}
}},
})
end
-- Utility node: this conductor is used to test rotation.
do
local get_rules = mesecon.horiz_rules_getter({{x = 1, y = 0, z = 0}, {x = -1, y = 0, z = 0}})
local off_spec = {conductor = {
state = mesecon.state.off,
rules = get_rules,
onstate = "mesecons:test_conductor_rot_on",
}}
local on_spec = {conductor = {
state = mesecon.state.on,
rules = get_rules,
offstate = "mesecons:test_conductor_rot_off",
}}
mesecon.register_node("mesecons:test_conductor_rot", {
description = "Rotatable Test Conductor",
on_rotate = mesecon.on_rotate_horiz,
}, {mesecons = off_spec}, {mesecons = on_spec})
end
-- Utility node: this is used to test multiple conductors within a single node.
do
local mesecons_spec = {conductor = {
rules = {
{{x = 1, y = 0, z = 0}, {x = 0, y = -1, z = 0}},
{{x = 0, y = 1, z = 0}, {x = 0, y = 0, z = -1}},
{{x = 0, y = 0, z = 1}, {x = -1, y = 0, z = 0}},
},
states = {
"mesecons:test_multiconductor_off", "mesecons:test_multiconductor_001",
"mesecons:test_multiconductor_010", "mesecons:test_multiconductor_011",
"mesecons:test_multiconductor_100", "mesecons:test_multiconductor_101",
"mesecons:test_multiconductor_110", "mesecons:test_multiconductor_on",
},
}}
for _, state in ipairs(mesecons_spec.conductor.states) do
minetest.register_node(state, {
description = "Test Multiconductor",
mesecons = mesecons_spec,
})
end
end
mesecon._test_autoconnects = {}
mesecon.register_autoconnect_hook("test", function(pos, node)
table.insert(mesecon._test_autoconnects, {pos, node})
end)
function mesecon._test_dig(pos)
local node = minetest.get_node(pos)
minetest.remove_node(pos)
mesecon.on_dignode(pos, node)
end
function mesecon._test_place(pos, node)
world.set_node(pos, node)
mesecon.on_placenode(pos, minetest.get_node(pos))
end
function mesecon._test_reset()
-- First let circuits settle by simulating many globalsteps.
for i = 1, 10 do
mineunit:execute_globalstep(60)
end
mesecon.queue.actions = {}
mesecon._test_effector_events = {}
mesecon._test_autoconnects = {}
end
mineunit:execute_globalstep(mesecon.setting("resumetime", 4) + 1)

View File

@ -0,0 +1,59 @@
mineunit("player")
fixture("mesecons")
fixture("mesecons_gamecompat")
local registered_on_player_receive_fields = {}
local old_register_on_player_receive_fields = minetest.register_on_player_receive_fields
function minetest.register_on_player_receive_fields(func)
old_register_on_player_receive_fields(func)
table.insert(registered_on_player_receive_fields, func)
end
mineunit:set_current_modname("mesecons_fpga")
mineunit:set_modpath("mesecons_fpga", "../mesecons_fpga")
sourcefile("../mesecons_fpga/init")
local fpga_user = Player("mesecons_fpga_user")
function mesecon._test_program_fpga(pos, program)
local node = minetest.get_node(pos)
assert.equal("mesecons_fpga:fpga", node.name:sub(1, 18))
local fields = {program = true}
for i, instr in ipairs(program) do
-- Translate the instruction into formspec fields.
local op1, act, op2, dst
if #instr == 3 then
act, op2, dst = unpack(instr)
else
assert.equal(4, #instr)
op1, act, op2, dst = unpack(instr)
end
fields[i .. "op1"] = op1
fields[i .. "act"] = (" "):rep(4 - #act) .. act
fields[i .. "op2"] = op2
fields[i .. "dst"] = dst
end
minetest.registered_nodes[node.name].on_rightclick(pos, node, fpga_user)
for _, func in ipairs(registered_on_player_receive_fields) do
if func(fpga_user, "mesecons:fpga", fields) then
break
end
end
end
function mesecon._test_copy_fpga_program(pos)
fpga_user:get_inventory():set_stack("main", 1, "mesecons_fpga:programmer")
local pt = {type = "node", under = vector.new(pos), above = vector.offset(pos, 0, 1, 0)}
fpga_user:do_place(pt)
return fpga_user:get_wielded_item()
end
function mesecon._test_paste_fpga_program(pos, tool)
fpga_user:get_inventory():set_stack("main", 1, tool)
local pt = {type = "node", under = vector.new(pos), above = vector.offset(pos, 0, 1, 0)}
fpga_user:do_use(pt)
end

View File

@ -0,0 +1,5 @@
fixture("mesecons")
mineunit:set_current_modname("mesecons_gamecompat")
mineunit:set_modpath("mesecons_gamecompat", "../mesecons_gamecompat")
sourcefile("../mesecons_gamecompat/init")

View File

@ -0,0 +1,12 @@
fixture("mesecons")
fixture("mesecons_gamecompat")
mineunit:set_current_modname("mesecons_luacontroller")
mineunit:set_modpath("mesecons_luacontroller", "../mesecons_luacontroller")
sourcefile("../mesecons_luacontroller/init")
function mesecon._test_program_luac(pos, code)
local node = minetest.get_node(pos)
assert.equal("mesecons_luacontroller:luacontroller", node.name:sub(1, 36))
return minetest.registered_nodes[node.name].mesecons.luacontroller.set_program(pos, code)
end

View File

@ -0,0 +1,45 @@
mineunit("protection")
fixture("mesecons")
mineunit:set_current_modname("mesecons_mvps")
mineunit:set_modpath("mesecons_mvps", "../mesecons_mvps")
sourcefile("../mesecons_mvps/init")
minetest.register_node("mesecons_mvps:test_stopper", {
description = "Test Stopper",
})
mesecon.register_mvps_stopper("mesecons_mvps:test_stopper")
minetest.register_node("mesecons_mvps:test_stopper_cond", {
description = "Test Stopper (Conditional)",
})
mesecon.register_mvps_stopper("mesecons_mvps:test_stopper_cond", function(node)
return node.param2 == 0
end)
minetest.register_node("mesecons_mvps:test_sticky", {
description = "Test Sticky",
mvps_sticky = function(pos)
local connected = {}
for i, rule in ipairs(mesecon.rules.alldirs) do
connected[i] = vector.add(pos, rule)
end
return connected
end,
})
mesecon._test_moves = {}
minetest.register_node("mesecons_mvps:test_on_move", {
description = "Test Moveable",
mesecon = {
on_mvps_move = function(pos, node, oldpos, meta)
table.insert(mesecon._test_moves, {pos, node, oldpos, meta})
end
},
})
local old_reset = mesecon._test_reset
function mesecon._test_reset()
mesecon._test_moves = {}
old_reset()
end

View File

@ -0,0 +1,6 @@
mineunit:set_current_modname("screwdriver")
screwdriver = {}
screwdriver.ROTATE_FACE = 1
screwdriver.ROTATE_AXIS = 2