Files
last-hearth/tests/engine_smoke.lua
T
2026-11-01 19:35:46 -05:00

170 lines
7.8 KiB
Lua
Executable File

-- Original MIT-licensed integration checks. Staged as a disposable world mod;
-- never copy this into the persistent play world. No engine globals are mocked.
local mode = core.settings:get("hearth_launcher_mode")
local token = core.settings:get("hearth_smoke_token")
assert(mode == "check" or mode == "smoke", "Invalid launcher test mode")
assert(token and token:match("^[%x%-]+$"), "Missing launcher test token")
local modpath = core.get_modpath(core.get_current_modname())
local finished = false
local function finish(ok, message)
if finished then return end
finished = true
if ok then
core.log("action", "LAST_HEARTH_" .. mode:upper() .. "_PASS " .. token)
else
core.log("error", "LAST_HEARTH_TEST_FAIL: " .. tostring(message))
end
core.request_shutdown("Last Hearth " .. mode .. " complete", false, 0)
end
local function guarded(fn)
local ok, message = pcall(fn)
if not ok then finish(false, message) end
end
local function syntax_check()
local manifest = dofile(modpath .. "/syntax_manifest.lua")
assert(#manifest > 0, "Empty syntax manifest")
for _, entry in ipairs(manifest) do
local chunk, message = loadfile(modpath .. "/syntax/" .. entry.file)
assert(chunk, entry.label .. ": " .. tostring(message))
end
core.log("action", "Last Hearth: compiled " .. #manifest .. " Lua files (standalone specs not executed)")
end
local function registry_check()
assert(type(hearth) == "table", "Real hearth global was not loaded")
assert(type(hearth.model) == "table", "hearth.model missing")
assert(type(hearth.players) == "table", "hearth.players missing")
assert(core.get_modpath("hearth"), "hearth mod missing")
for _, name in ipairs({"default", "doors", "farming", "fire", "stairs", "wool", "sfinv"}) do
assert(not core.get_modpath(name), "Unexpected MTG dependency: " .. name)
end
for name in pairs(core.registered_items) do
assert(not name:match("^default:"), "MTG item leaked into standalone game: " .. name)
end
for _, name in ipairs({"stone", "soil", "grass", "sand", "water_source", "water_flowing",
"log", "leaves", "loose_stone", "sticks", "berry_bush", "reeds", "planks",
"wall", "roof", "fire", "fire_lit"}) do
assert(core.registered_nodes["hearth:" .. name], "Missing node: " .. name)
end
for _, name in ipairs({"berries", "raw_food", "cooked_food", "vessel", "water_raw",
"water_clean", "knife", "axe", "pick", "spear"}) do
assert(core.registered_items["hearth:" .. name], "Missing item: " .. name)
end
for _, name in ipairs({"knife", "axe", "pick", "spear", "vessel", "fire", "wall",
"roof", "planks", "sticks", "raw_food"}) do
local output = "hearth:" .. name
local recipe = core.get_craft_recipe(output)
assert(recipe.items and next(recipe.items), "Missing craft: " .. output)
for _, ingredient in pairs(recipe.items) do
assert(ingredient == "" or core.registered_items[ingredient], "Unknown ingredient: " .. ingredient)
end
local inputs = {}
for index = 1, (recipe.width == 0 and #recipe.items or recipe.width * 3) do
inputs[index] = ItemStack(recipe.items[index] or "")
end
local width = recipe.width > 0 and recipe.width or #inputs
local result = core.get_craft_result({method = "normal", width = width, items = inputs})
assert(result.item:get_name() == output, "Engine craft result mismatch: " .. output)
assert(result.item:get_count() == ItemStack(recipe.output):get_count(), "Craft quantity mismatch: " .. output)
end
assert(core.registered_aliases.mapgen_stone == "hearth:stone", "Missing mapgen stone alias")
assert(core.registered_aliases.mapgen_water_source == "hearth:water_source", "Missing water alias")
assert(core.registered_biomes.hearth_temperate, "Missing temperate biome")
assert(core.registered_biomes.hearth_riverbank, "Missing riverbank biome")
assert(core.settings:get_bool("enable_pvp") == false, "PvP must be disabled")
assert(core.settings:get_bool("secure.enable_security") == true, "Mod security must be enabled")
assert(core.settings:get("bind_address") == "127.0.0.1", "Server must bind loopback only")
end
local function unit_check()
-- Each standalone harness receives its own globals and os table. Mocked core,
-- hearth and os.time never replace globals of the running game.
local manifest = dofile(modpath .. "/syntax_manifest.lua")
local lookup = {}
for _, entry in ipairs(manifest) do lookup[entry.label] = modpath .. "/syntax/" .. entry.file end
local count = 0
for label, filename in pairs(lookup) do
if label:match("_spec%.lua$") then
local module = label:match("tests/(.+)_spec%.lua$")
local target = assert(lookup["mods/hearth/" .. module .. ".lua"], "Missing test module")
local env = setmetatable({arg = {target}, os = {}}, {__index = _G})
for k, v in pairs(os) do env.os[k] = v end
env._G = env
env.dofile = function(path)
assert(path == target, "Unit harness attempted unexpected file access")
local chunk = assert(loadfile(path)); setfenv(chunk, env); return chunk()
end
local chunk = assert(loadfile(filename)); setfenv(chunk, env); chunk()
count = count + 1
end
end
assert(count >= 2, "Expected model and content regression suites")
core.log("action", "Last Hearth: " .. count .. " isolated unit suites executed")
end
local function emerge_check()
local callbacks = 0
core.emerge_area({x = -64, y = -32, z = -64}, {x = 64, y = 96, z = 64},
function(_, action, remaining)
if finished then return end
guarded(function()
assert(action ~= core.EMERGE_ERRORED and action ~= core.EMERGE_CANCELLED,
"Map emergence failed or was cancelled")
callbacks = callbacks + 1
if remaining ~= 0 then return end
-- Inspect after mapgen callbacks have completed, on a server step.
core.after(0, function()
guarded(function()
assert(callbacks > 0, "No emerge callbacks received")
local material = false
for z = -16, 16, 4 do
for y = -32, 16, 4 do
for x = -16, 16, 4 do
local node = core.get_node_or_nil({x = x, y = y, z = z})
assert(node and node.name ~= "ignore", "Emerged map contains unloaded nodes")
assert(core.registered_nodes[node.name], "Unregistered generated node: " .. node.name)
assert(node.name == "air" or node.name:match("^hearth:"),
"Foreign generated node: " .. node.name)
if node.name:match("^hearth:") then material = true end
end
end
end
assert(material, "Mapgen produced no hearth terrain in the test volume")
local resources = {}
for _, name in ipairs({"grass", "loose_stone", "sticks", "berry_bush", "reeds", "log", "water_source"}) do
local nodes = core.find_nodes_in_area({x = -64, y = -16, z = -64}, {x = 64, y = 96, z = 64}, {"hearth:" .. name})
resources[#resources + 1] = name .. "=" .. #nodes
assert(#nodes > 0, "Starting region missing required resource: " .. name)
end
core.log("action", "Last Hearth starting resources: " .. table.concat(resources, ", "))
local p = {x = 0, y = 85, z = 0}
core.set_node(vector.offset(p, 0, 3, 0), {name = "hearth:roof"})
for _, d in ipairs({{1,0},{-1,0},{0,1},{0,-1}}) do
core.set_node(vector.offset(p, d[1]*2, 1, d[2]*2), {name = "hearth:wall"})
end
local env = hearth.environment(p)
assert(env.roof and env.shelter == 1, "A roof and four walls must enclose a shelter")
core.remove_node(vector.offset(p, 0, 3, 0))
assert(hearth.environment(p).shelter == 0, "Walls without a roof are exposed")
finish(true)
end)
end)
end)
end)
end
core.after(1, function()
guarded(function()
syntax_check()
if mode == "check" then finish(true); return end
registry_check()
unit_check()
emerge_check()
end)
end)
core.after(60, function() finish(false, "Engine test deadline exceeded") end)