mirror of
				https://github.com/minetest-mods/mesecons.git
				synced 2025-11-04 12:55:29 +01:00 
			
		
		
		
	Add core unit tests
This commit is contained in:
		@@ -34,3 +34,11 @@ globals = {"mesecon"}
 | 
			
		||||
files["mesecons/actionqueue.lua"] = {
 | 
			
		||||
	globals = {"minetest.registered_globalsteps"},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
files["*/spec/**/*.lua"] = {
 | 
			
		||||
	read_globals = {"assert", "fixture", "mineunit", "sourcefile", "world"},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
files["mesecons/spec/fixtures/voxelmanip.lua"] = {
 | 
			
		||||
	globals = {"minetest.get_voxel_manip"},
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										62
									
								
								mesecons/spec/action_spec.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								mesecons/spec/action_spec.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
require("mineunit")
 | 
			
		||||
 | 
			
		||||
fixture("mesecons")
 | 
			
		||||
 | 
			
		||||
describe("action queue", function()
 | 
			
		||||
	local layout = {
 | 
			
		||||
		{{x =  1, y = 0, z = 0}, "mesecons:test_receptor_off"},
 | 
			
		||||
		{{x =  0, y = 0, z = 0}, "mesecons:test_conductor_off"},
 | 
			
		||||
		{{x = -1, y = 0, z = 0}, "mesecons:test_conductor_off"},
 | 
			
		||||
		{{x =  0, y = 1, z = 0}, "mesecons:test_effector"},
 | 
			
		||||
		{{x = -1, y = 1, z = 0}, "mesecons:test_effector"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	before_each(function()
 | 
			
		||||
		world.layout(layout)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	after_each(function()
 | 
			
		||||
		mesecon._test_reset()
 | 
			
		||||
		world.clear()
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("executes in order", function()
 | 
			
		||||
		mesecon.swap_node_force(layout[1][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal(2, #mesecon._test_effector_events)
 | 
			
		||||
		assert.same({"on", layout[4][1]}, mesecon._test_effector_events[1])
 | 
			
		||||
		assert.same({"on", layout[5][1]}, mesecon._test_effector_events[2])
 | 
			
		||||
 | 
			
		||||
		mesecon.swap_node_force(layout[1][1], "mesecons:test_receptor_off")
 | 
			
		||||
		mesecon.receptor_off(layout[1][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal(4, #mesecon._test_effector_events)
 | 
			
		||||
		assert.same({"off", layout[4][1]}, mesecon._test_effector_events[3])
 | 
			
		||||
		assert.same({"off", layout[5][1]}, mesecon._test_effector_events[4])
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("ignores overwritten actions", function()
 | 
			
		||||
		mesecon.swap_node_force(layout[1][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs)
 | 
			
		||||
		mesecon.swap_node_force(layout[1][1], "mesecons:test_receptor_off")
 | 
			
		||||
		mesecon.receptor_off(layout[1][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal(0, #mesecon._test_effector_events)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("delays actions", function()
 | 
			
		||||
		mesecon.swap_node_force(layout[1][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon.queue:add_action(layout[1][1], "receptor_on", {mesecon.rules.alldirs}, 1, nil)
 | 
			
		||||
		mineunit:execute_globalstep(0.1)
 | 
			
		||||
		mineunit:execute_globalstep(1)
 | 
			
		||||
		assert.equal(0, #mesecon._test_effector_events)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal(0, #mesecon._test_effector_events)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal(2, #mesecon._test_effector_events)
 | 
			
		||||
	end)
 | 
			
		||||
end)
 | 
			
		||||
							
								
								
									
										128
									
								
								mesecons/spec/fixtures/mesecons.lua
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								mesecons/spec/fixtures/mesecons.lua
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
mineunit("core")
 | 
			
		||||
mineunit("server")
 | 
			
		||||
 | 
			
		||||
fixture("voxelmanip")
 | 
			
		||||
 | 
			
		||||
sourcefile("init")
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
do
 | 
			
		||||
	mesecon._test_effector_events = {}
 | 
			
		||||
	local function action_on(pos, node)
 | 
			
		||||
		table.insert(mesecon._test_effector_events, {"on", pos})
 | 
			
		||||
		node.param2 = node.param2 % 64 + 128
 | 
			
		||||
		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
 | 
			
		||||
		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
 | 
			
		||||
		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
 | 
			
		||||
 | 
			
		||||
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()
 | 
			
		||||
	for i = 1, 30 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)
 | 
			
		||||
							
								
								
									
										91
									
								
								mesecons/spec/fixtures/voxelmanip.lua
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								mesecons/spec/fixtures/voxelmanip.lua
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
mineunit("world")
 | 
			
		||||
mineunit("common/vector")
 | 
			
		||||
mineunit("game/misc")
 | 
			
		||||
 | 
			
		||||
local VoxelManip = {}
 | 
			
		||||
 | 
			
		||||
local function create(p1, p2)
 | 
			
		||||
	local vm = setmetatable({nodes = {}}, VoxelManip)
 | 
			
		||||
 | 
			
		||||
	if type(p1) == "table" and type(p2) == "table" then
 | 
			
		||||
		vm:read_from_map(p1, p2)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	return vm
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function VoxelManip:read_from_map(p1, p2)
 | 
			
		||||
	assert.same(p1, p2)
 | 
			
		||||
	assert.is_nil(self.emin)
 | 
			
		||||
 | 
			
		||||
	local blockpos = vector.floor(vector.divide(p1, minetest.MAP_BLOCKSIZE))
 | 
			
		||||
	local emin = vector.multiply(blockpos, minetest.MAP_BLOCKSIZE)
 | 
			
		||||
	local emax = vector.add(emin, minetest.MAP_BLOCKSIZE - 1)
 | 
			
		||||
	self.emin, self.emax = emin, emax
 | 
			
		||||
 | 
			
		||||
	local p = vector.new(emin)
 | 
			
		||||
	while p.z <= emax.z do
 | 
			
		||||
		while p.y <= emax.y do
 | 
			
		||||
			while p.x <= emax.x do
 | 
			
		||||
				local node = world.get_node(p)
 | 
			
		||||
				if node then
 | 
			
		||||
					self.nodes[minetest.hash_node_position(p)] = node
 | 
			
		||||
				end
 | 
			
		||||
				p.x = p.x + 1
 | 
			
		||||
			end
 | 
			
		||||
			p.x = emin.x
 | 
			
		||||
			p.y = p.y + 1
 | 
			
		||||
		end
 | 
			
		||||
		p.y = emin.y
 | 
			
		||||
		p.z = p.z + 1
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function VoxelManip:get_node_at(pos)
 | 
			
		||||
	local node = self.nodes[minetest.hash_node_position(pos)]
 | 
			
		||||
	if node then
 | 
			
		||||
		return {name = node.name, param1 = node.param1, param2 = node.param2}
 | 
			
		||||
	else
 | 
			
		||||
		return {name = "ignore", param1 = 0, param2 = 0}
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function VoxelManip:set_node_at(pos, node)
 | 
			
		||||
	local emin, emax = self.emin, self.emax
 | 
			
		||||
	if pos.x < emin.x or pos.y < emin.y or pos.z < emin.z or pos.x > emax.x or pos.y > emax.y or pos.z > emax.z then
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
	self.nodes[minetest.hash_node_position(pos)] = {name = node.name, param1 = node.param1, param2 = node.param2}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function VoxelManip:write_to_map()
 | 
			
		||||
	local emin, emax = self.emin, self.emax
 | 
			
		||||
	local p = vector.new(emin)
 | 
			
		||||
	while p.z <= emax.z do
 | 
			
		||||
		while p.y <= emax.y do
 | 
			
		||||
			while p.x <= emax.x do
 | 
			
		||||
				local node = self.nodes[minetest.hash_node_position(p)]
 | 
			
		||||
				if node ~= nil or world.get_node(p) ~= nil then
 | 
			
		||||
					world.swap_node(p, node)
 | 
			
		||||
				end
 | 
			
		||||
				p.x = p.x + 1
 | 
			
		||||
			end
 | 
			
		||||
			p.x = emin.x
 | 
			
		||||
			p.y = p.y + 1
 | 
			
		||||
		end
 | 
			
		||||
		p.y = emin.y
 | 
			
		||||
		p.z = p.z + 1
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function VoxelManip.update_map()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function minetest.get_voxel_manip(p1, p2)
 | 
			
		||||
	return create(p1, p2)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
mineunit.export_object(VoxelManip, {
 | 
			
		||||
	name = "VoxelManip",
 | 
			
		||||
	constructor = create,
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										0
									
								
								mesecons/spec/mineunit.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								mesecons/spec/mineunit.conf
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										141
									
								
								mesecons/spec/service_spec.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								mesecons/spec/service_spec.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
			
		||||
require("mineunit")
 | 
			
		||||
 | 
			
		||||
fixture("mesecons")
 | 
			
		||||
 | 
			
		||||
describe("placement/digging service", function()
 | 
			
		||||
	local layout = {
 | 
			
		||||
		{{x =  1, y = 0, z = 0}, "mesecons:test_receptor_on"},
 | 
			
		||||
		{{x =  0, y = 0, z = 0}, "mesecons:test_conductor_on"},
 | 
			
		||||
		{{x = -1, y = 0, z = 0}, "mesecons:test_conductor_on"},
 | 
			
		||||
		{{x =  0, y = 1, z = 0}, "mesecons:test_effector"},
 | 
			
		||||
		{{x = -2, y = 0, z = 0}, "mesecons:test_effector"},
 | 
			
		||||
		{{x =  2, y = 0, z = 0}, "mesecons:test_effector"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	before_each(function()
 | 
			
		||||
		world.layout(layout)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	after_each(function()
 | 
			
		||||
		mesecon._test_reset()
 | 
			
		||||
		world.clear()
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("updates components when a receptor changes", function()
 | 
			
		||||
		mesecon._test_dig(layout[1][1])
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(layout[2][1]).name)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal(3, #mesecon._test_effector_events)
 | 
			
		||||
 | 
			
		||||
		mesecon._test_place(layout[1][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal("mesecons:test_conductor_on", world.get_node(layout[2][1]).name)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal(6, #mesecon._test_effector_events)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("updates components when a conductor changes", function()
 | 
			
		||||
		mesecon._test_dig(layout[2][1])
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(layout[3][1]).name)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal(2, #mesecon._test_effector_events)
 | 
			
		||||
 | 
			
		||||
		mesecon._test_place(layout[2][1], "mesecons:test_conductor_off")
 | 
			
		||||
		assert.equal("mesecons:test_conductor_on", world.get_node(layout[2][1]).name)
 | 
			
		||||
		assert.equal("mesecons:test_conductor_on", world.get_node(layout[3][1]).name)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal(4, #mesecon._test_effector_events)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("updates effectors on placement", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 1}
 | 
			
		||||
		mesecon._test_place(pos, "mesecons:test_effector")
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal(tonumber("10100000", 2), world.get_node(pos).param2)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("updates multiconductors on placement", function()
 | 
			
		||||
		local pos = {x = 0, y = 0, z = 1}
 | 
			
		||||
		mesecon._test_place(pos, "mesecons:test_multiconductor_off")
 | 
			
		||||
		assert.equal("mesecons:test_multiconductor_010", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("turns off conductors on placement", function()
 | 
			
		||||
		local pos = {x = 3, y = 0, z = 0}
 | 
			
		||||
		mesecon._test_place(pos, "mesecons:test_conductor_on")
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	-- Will work once #584 is merged.
 | 
			
		||||
	pending("turns off multiconductors on placement", function()
 | 
			
		||||
		local pos = {x = 3, y = 0, z = 0}
 | 
			
		||||
		mesecon._test_place(pos, "mesecons:test_multiconductor_on")
 | 
			
		||||
		assert.equal("mesecons:test_multiconductor_off", world.get_node(pos).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("triggers autoconnect hooks", function()
 | 
			
		||||
		mesecon._test_dig(layout[2][1])
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal(1, #mesecon._test_autoconnects)
 | 
			
		||||
 | 
			
		||||
		mesecon._test_place(layout[2][1], layout[2][2])
 | 
			
		||||
		assert.equal(2, #mesecon._test_autoconnects)
 | 
			
		||||
	end)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
describe("overheating service", function()
 | 
			
		||||
	local layout = {
 | 
			
		||||
		{{x = 0, y = 0, z = 0}, "mesecons:test_receptor_off"},
 | 
			
		||||
		{{x = 1, y = 0, z = 0}, "mesecons:test_effector"},
 | 
			
		||||
		{{x = 2, y = 0, z = 0}, "mesecons:test_receptor_on"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	before_each(function()
 | 
			
		||||
		world.layout(layout)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	after_each(function()
 | 
			
		||||
		mesecon._test_reset()
 | 
			
		||||
		world.clear()
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("tracks heat", function()
 | 
			
		||||
		mesecon.do_overheat(layout[2][1])
 | 
			
		||||
		assert.equal(1, mesecon.get_heat(layout[2][1]))
 | 
			
		||||
		mesecon.do_cooldown(layout[2][1])
 | 
			
		||||
		assert.equal(0, mesecon.get_heat(layout[2][1]))
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("cools over time", function()
 | 
			
		||||
		mesecon.do_overheat(layout[2][1])
 | 
			
		||||
		assert.equal(1, mesecon.get_heat(layout[2][1]))
 | 
			
		||||
		mineunit:execute_globalstep(60)
 | 
			
		||||
		mineunit:execute_globalstep(60)
 | 
			
		||||
		mineunit:execute_globalstep(60)
 | 
			
		||||
		assert.equal(0, mesecon.get_heat(layout[2][1]))
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("tracks movement", function()
 | 
			
		||||
		local oldpos = layout[2][1]
 | 
			
		||||
		local pos = vector.offset(oldpos, 0, 1, 0)
 | 
			
		||||
		mesecon.do_overheat(oldpos)
 | 
			
		||||
		mesecon.move_hot_nodes({{pos = pos, oldpos = oldpos}})
 | 
			
		||||
		assert.equal(0, mesecon.get_heat(oldpos))
 | 
			
		||||
		assert.equal(1, mesecon.get_heat(pos))
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("causes overheating", function()
 | 
			
		||||
		repeat
 | 
			
		||||
			if mesecon.flipstate(layout[1][1], minetest.get_node(layout[1][1])) == "on" then
 | 
			
		||||
				mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs)
 | 
			
		||||
			else
 | 
			
		||||
				mesecon.receptor_off(layout[1][1], mesecon.rules.alldirs)
 | 
			
		||||
			end
 | 
			
		||||
			mineunit:execute_globalstep(0)
 | 
			
		||||
		until minetest.get_node(layout[2][1]).name ~= "mesecons:test_effector"
 | 
			
		||||
		assert.same({"overheat", layout[2][1]}, mesecon._test_effector_events[#mesecon._test_effector_events])
 | 
			
		||||
		assert.equal(0, mesecon.get_heat(layout[2][1]))
 | 
			
		||||
	end)
 | 
			
		||||
end)
 | 
			
		||||
							
								
								
									
										116
									
								
								mesecons/spec/state_spec.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								mesecons/spec/state_spec.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
require("mineunit")
 | 
			
		||||
 | 
			
		||||
fixture("mesecons")
 | 
			
		||||
 | 
			
		||||
describe("state", function()
 | 
			
		||||
	local layout = {
 | 
			
		||||
		{{x =  1, y =  0, z = 0}, "mesecons:test_receptor_off"},
 | 
			
		||||
		{{x =  0, y =  1, z = 0}, "mesecons:test_receptor_off"},
 | 
			
		||||
		{{x =  0, y =  0, z = 0}, "mesecons:test_conductor_off"},
 | 
			
		||||
		{{x = -1, y =  0, z = 0}, "mesecons:test_effector"},
 | 
			
		||||
		{{x =  2, y =  0, z = 0}, "mesecons:test_effector"},
 | 
			
		||||
		{{x =  0, y = -1, z = 0}, "mesecons:test_effector"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	before_each(function()
 | 
			
		||||
		world.layout(layout)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	after_each(function()
 | 
			
		||||
		mesecon._test_reset()
 | 
			
		||||
		world.clear()
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("turns on", function()
 | 
			
		||||
		mesecon.swap_node_force(layout[1][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal("mesecons:test_conductor_on", world.get_node(layout[3][1]).name)
 | 
			
		||||
		assert.equal(tonumber("10000001", 2), world.get_node(layout[4][1]).param2)
 | 
			
		||||
		assert.equal(tonumber("10000010", 2), world.get_node(layout[5][1]).param2)
 | 
			
		||||
		assert.equal(tonumber("10000100", 2), world.get_node(layout[6][1]).param2)
 | 
			
		||||
 | 
			
		||||
		mesecon.swap_node_force(layout[2][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon.receptor_on(layout[2][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal("mesecons:test_conductor_on", world.get_node(layout[3][1]).name)
 | 
			
		||||
		assert.equal(tonumber("10000001", 2), world.get_node(layout[4][1]).param2)
 | 
			
		||||
		assert.equal(tonumber("10000010", 2), world.get_node(layout[5][1]).param2)
 | 
			
		||||
		assert.equal(tonumber("10000100", 2), world.get_node(layout[6][1]).param2)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("turns off", function()
 | 
			
		||||
		mesecon.swap_node_force(layout[1][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon.swap_node_force(layout[2][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs)
 | 
			
		||||
		mesecon.receptor_on(layout[2][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
 | 
			
		||||
		mesecon.swap_node_force(layout[1][1], "mesecons:test_receptor_off")
 | 
			
		||||
		mesecon.receptor_off(layout[1][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal("mesecons:test_conductor_on", world.get_node(layout[3][1]).name)
 | 
			
		||||
		assert.equal(tonumber("10000001", 2), world.get_node(layout[4][1]).param2)
 | 
			
		||||
		assert.equal(tonumber("00000000", 2), world.get_node(layout[5][1]).param2)
 | 
			
		||||
		assert.equal(tonumber("10000100", 2), world.get_node(layout[6][1]).param2)
 | 
			
		||||
 | 
			
		||||
		mesecon.swap_node_force(layout[2][1], "mesecons:test_receptor_off")
 | 
			
		||||
		mesecon.receptor_off(layout[2][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal("mesecons:test_conductor_off", world.get_node(layout[3][1]).name)
 | 
			
		||||
		assert.equal(tonumber("00000000", 2), world.get_node(layout[4][1]).param2)
 | 
			
		||||
		assert.equal(tonumber("00000000", 2), world.get_node(layout[5][1]).param2)
 | 
			
		||||
		assert.equal(tonumber("00000000", 2), world.get_node(layout[6][1]).param2)
 | 
			
		||||
	end)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
describe("multiconductor", function()
 | 
			
		||||
	local layout = {
 | 
			
		||||
		{{x =  1, y = 0, z =  0}, "mesecons:test_receptor_off"},
 | 
			
		||||
		{{x =  0, y = 1, z =  0}, "mesecons:test_receptor_off"},
 | 
			
		||||
		{{x =  0, y = 0, z =  1}, "mesecons:test_receptor_off"},
 | 
			
		||||
		{{x =  0, y = 0, z =  0}, "mesecons:test_multiconductor_off"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	before_each(function()
 | 
			
		||||
		world.layout(layout)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	after_each(function()
 | 
			
		||||
		world.clear()
 | 
			
		||||
		mesecon._test_reset()
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("separates its subparts", function()
 | 
			
		||||
		mesecon.swap_node_force(layout[1][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal("mesecons:test_multiconductor_001", world.get_node(layout[4][1]).name)
 | 
			
		||||
 | 
			
		||||
		mesecon.swap_node_force(layout[2][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon.receptor_on(layout[2][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal("mesecons:test_multiconductor_011", world.get_node(layout[4][1]).name)
 | 
			
		||||
 | 
			
		||||
		mesecon.swap_node_force(layout[3][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon.receptor_on(layout[3][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal("mesecons:test_multiconductor_on", world.get_node(layout[4][1]).name)
 | 
			
		||||
	end)
 | 
			
		||||
 | 
			
		||||
	it("loops through itself", function()
 | 
			
		||||
		-- Make a loop.
 | 
			
		||||
		world.set_node({x = 0, y = -1, z = 0}, "mesecons:test_conductor_off")
 | 
			
		||||
		world.set_node({x = -1, y = -1, z = 0}, "mesecons:test_conductor_off")
 | 
			
		||||
		world.set_node({x = -1, y = 0, z = 0}, "mesecons:test_conductor_off")
 | 
			
		||||
 | 
			
		||||
		mesecon.swap_node_force(layout[1][1], "mesecons:test_receptor_on")
 | 
			
		||||
		mesecon.receptor_on(layout[1][1], mesecon.rules.alldirs)
 | 
			
		||||
		mineunit:execute_globalstep()
 | 
			
		||||
		assert.equal("mesecons:test_multiconductor_101", world.get_node(layout[4][1]).name)
 | 
			
		||||
	end)
 | 
			
		||||
end)
 | 
			
		||||
		Reference in New Issue
	
	Block a user