-- Mock-only security/geometry/telemetry checks; never starts an engine. local target = assert(arg[1], "course.lua path required") local total = 0 local NONCE = "12345678-1234-4234-8234-123456789abc" -- Public test fixture, not a credential. local function test(name, fn) local old_core, old_hearth, old_io = core, hearth, io local ok, err = pcall(fn) core, hearth, io = old_core, old_hearth, old_io assert(ok, name .. ": " .. tostring(err)) total = total + 1; print("ok " .. total .. " - " .. name) end local function key(p) return p.x .. ":" .. p.y .. ":" .. p.z end local function harness(options) local h = {settings = {hearth_environment = "local", hearth_m1_course = true, hearth_m1_course_nonce = NONCE}, storage = {}, marker = NONCE .. "\n", worldpath = "C:/isolated/course", single = true, time = 10, commands = {}, steps = {}, players = {}, messages = {}, registered = {}, nodes = {}, writes = 0, reads = 0, emerges = 0, storage_writes = 0, priv_checks = 0, io_reads = 0} for k, v in pairs(options or {}) do h[k] = v end local C = { settings = {get = function(_, k) return h.settings[k] end, get_bool = function(_, k) return h.settings[k] == true end}, get_us_time = function() return h.time * 1000000 end, get_worldpath = function() return h.worldpath end, is_singleplayer = function() return h.single end, check_player_privs = function(name, privs) assert(name and privs.server == true); h.priv_checks = h.priv_checks + 1 return h.privileged == true end, register_chatcommand = function(name, def) h.commands[name] = def end, register_globalstep = function(fn) h.steps[#h.steps + 1] = fn end, register_on_leaveplayer = function(fn) h.leave = fn end, register_on_dieplayer = function(fn) h.die = fn end, register_node = function(name, def) h.registered[name] = def end, get_player_by_name = function(name) return h.players[name] end, chat_send_player = function(name, msg) h.messages[#h.messages + 1] = {name, msg} end, get_node_or_nil = function(p) h.reads = h.reads + 1 if h.unloaded and p.x == 90 and p.y == 58 and p.z == 40 then return nil end if h.ignore and p.x == 90 and p.y == 58 and p.z == 40 then return {name = "ignore"} end return {name = h.nodes[key(p)] or "air"} end, set_node = function(p, n) assert(p.x >= 0 and p.x <= 90 and p.y >= 48 and p.y <= 58 and p.z >= 0 and p.z <= 40) h.writes = h.writes + 1; assert(h.writes < 45000, "Unbounded generation") h.nodes[key(p)] = n.name end, emerge_area = function(a, b, cb) assert(a.x == 0 and a.y == 48 and a.z == 0 and b.x == 90 and b.y == 58 and b.z == 40) h.emerges = h.emerges + 1; h.callback = cb end, } local H = {players = {}, sessions = {}, texture = function(color) return "texture:" .. color end, storage = {get_string = function(_, k) return h.storage[k] or "" end, set_string = function(_, k, v) h.storage_writes = h.storage_writes + 1; h.storage[k] = v end}, feedback = function(_, msg) h.feedback = msg end} local fakeio = {open = function(path, mode) assert(path == h.worldpath:gsub("\\", "/"):gsub("/+$", "") .. "/.hearth-m1-course-nonce" and mode == "rb") if h.marker == false then return nil end return {read = function(_, size) assert(size == 65); h.io_reads = h.io_reads + 1; return h.marker:sub(1, size) end, close = function() h.closed = true end} end} function h.load() core, hearth, io = C, H, fakeio h.module = dofile(target); return h.module end function h.player(name) local p = {name = name or "alice", hp = 20, pos = {x = 0, y = 0, z = 0}, grants = 0, teleports = 0} function p:is_player() return true end function p:get_player_name() return self.name end function p:get_hp() return self.hp end function p:get_pos() return self.pos end function p:set_hp(n) self.hp = n end function p:set_pos(pos) self.pos = pos; self.teleports = self.teleports + 1 end function p:set_velocity(v) assert(v.x == 0 and v.y == 0 and v.z == 0) end function p:get_inventory() return {set_list = function(_, list, items) assert(list == "main"); self.grants = self.grants + 1; self.kit = items end} end h.players[p.name] = p; H.players[p.name] = {food = 13, water = 12}; H.sessions[p.name] = {} return p, H.sessions[p.name] end function h.command(name, param) return h.commands.course.func(name or "alice", param or "") end function h.complete() h.callback({x = 0, y = 0, z = 0}, 4, 0) end function h.tick(dt) h.time = h.time + dt; for _, step in ipairs(h.steps) do step(dt) end end function h.node(x, y, z) return h.nodes[key({x = x, y = y, z = z})] end h.C, h.H = C, H return h end test("default boot is inert before join and generation requires opt-in", function() local h = harness(); h.load() assert(h.storage.m1_course_world_nonce == NONCE and h.closed and h.io_reads == 1) assert(h.emerges == 0 and h.writes == 0) assert(not h.command()); assert(h.emerges == 0) h.player(); h.tick(1); assert(h.emerges == 0 and h.writes == 0) end) test("disabled setting cannot enroll or generate even with matching marker", function() local h = harness(); h.settings.hearth_m1_course = false; h.load(); h.player() assert(not h.command() and h.storage_writes == 0 and h.io_reads == 0 and h.emerges == 0) end) test("production hard-denies server admins and never touches marker or storage", function() local h = harness({privileged = true}); h.settings.hearth_environment = "production" h.load(); h.player(); assert(not h.command()) assert(h.writes == 0 and h.storage_writes == 0 and h.io_reads == 0 and h.emerges == 0) end) test("invalid and dedicated-local deployments fail closed", function() for _, env in ipairs({"typo", "local"}) do local h = harness({single = false, privileged = true}); h.settings.hearth_environment = env h.load(); h.player(); assert(not h.command() and h.storage_writes == 0) end end) test("staging explicitly checks server privilege at command and completion", function() local h = harness({single = false}); h.settings.hearth_environment = "staging" h.load(); local p = h.player(); assert(not h.command() and h.priv_checks > 0) h.privileged = true; assert(h.command()); assert(h.emerges == 1 and p.grants == 0) h.privileged = false; h.complete(); assert(h.writes == 0 and p.grants == 0) end) test("missing environment defaults to production for a dedicated server", function() local h = harness({single = false, privileged = true}); h.settings.hearth_environment = nil h.load(); h.player(); assert(not h.command() and h.storage_writes == 0) end) test("settings alone cannot bless normal world names", function() for _, path in ipairs({"C:/worlds/last_hearth", "C:/worlds/course-not-really"}) do local h = harness({worldpath = path}); h.load(); h.player() assert(not h.command() and h.io_reads == 0 and h.storage_writes == 0) end end) test("missing, mismatched and oversized world marker files deny enrollment", function() for _, marker in ipairs({false, "wrong", NONCE .. string.rep("x", 100)}) do local h = harness({marker = marker}); h.load(); h.player() assert(not h.command() and h.storage_writes == 0 and h.emerges == 0) end end) test("malformed nonce fails without file access", function() local h = harness(); h.settings.hearth_m1_course_nonce = "../course" h.load(); h.player(); assert(not h.command() and h.io_reads == 0) end) test("saved spawn, claims, location or migration backups prevent first enrollment", function() for _, k in ipairs({"spawn", "claims", "location", "m0_backup:spawn", "m0_backup:claims", "m0_backup:location"}) do local h = harness(); h.storage[k] = "{}"; h.load(); h.player() assert(not h.command() and h.storage_writes == 0 and h.emerges == 0) end end) test("matching enrolled world may restart after normal spawn save, mismatched storage denies", function() local h = harness(); h.storage.m1_course_world_nonce = NONCE; h.storage.spawn = "saved" h.load(); h.player(); assert(h.command() and h.storage_writes == 0) local other = harness(); other.storage.m1_course_world_nonce = "other" other.load(); other.player(); assert(not other.command() and other.storage_writes == 0) end) test("loading after a player session exists cannot enroll an old world", function() local h = harness(); h.player(); h.load(); assert(not h.command() and h.storage_writes == 0) end) test("no join kit or teleport before all emergence callbacks finish", function() local h = harness(); h.load(); local p = h.player(); assert(h.command()) h.callback({}, 4, 1); assert(h.writes == 0 and p.grants == 0 and p.teleports == 0) h.complete(); assert(h.writes > 41041 and p.grants == 1 and p.teleports == 1) assert(p.pos.x == 5 and p.pos.y == 50.5 and p.pos.z == 5 and h.H.players.alice.food == 100) end) test("generation is single-instance across opt-ins, retries and duplicate callbacks", function() local h = harness(); h.load(); local a, b = h.player("alice"), h.player("bob") assert(h.command("alice") and h.command("bob") and h.emerges == 1) h.complete(); local writes = h.writes; h.complete() assert(a.grants == 1 and b.grants == 1 and h.writes == writes) assert(h.command("alice", "retry")); assert(h.emerges == 1 and h.writes == writes and a.grants == 2) assert(dofile(target) == h.module and #h.steps == 1) end) test("loaded preflight fails before the first write", function() for _, mode in ipairs({"unloaded", "ignore"}) do local h = harness(); h[mode] = true; h.load(); local p = h.player() assert(h.command()); h.complete(); assert(h.writes == 0 and p.grants == 0) assert(not h.command()) end end) test("cancelled or errored emergence does not generate or grant", function() for action = 0, 1 do local h = harness(); h.load(); local p = h.player(); h.command() h.callback({}, action, 1); h.complete(); assert(h.writes == 0 and p.grants == 0) end end) test("revoked settings and storage identity prevent deferred writes", function() for _, mode in ipairs({"production", "disabled", "nonce", "storage"}) do local h = harness(); h.load(); local p = h.player(); h.command() if mode == "production" then h.settings.hearth_environment = "production" elseif mode == "disabled" then h.settings.hearth_m1_course = false elseif mode == "nonce" then h.settings.hearth_m1_course_nonce = "changed" else h.storage.m1_course_world_nonce = "changed" end h.complete(); assert(h.writes == 0 and p.grants == 0) end end) test("disconnect/rejoin cannot inherit deferred consent or a kit", function() local h = harness(); h.load(); local old = h.player(); h.command() local stale_callback = h.callback h.leave(old); local new = h.player(); h.complete() assert(h.writes == 0 and old.grants == 0 and new.grants == 0) assert(h.command()); stale_callback({}, 4, 0) assert(h.writes == 0 and new.grants == 0) h.complete(); assert(h.writes > 0 and new.grants == 1) end) test("death, stale sessions and pending arrival invalidate requests", function() local h = harness(); h.load(); local p, session = h.player() session.waiting = true; assert(not h.command()); session.waiting = false p.hp = 0; assert(not h.command()); p.hp = 20 h.command(); h.H.sessions.alice = {}; h.complete(); assert(h.writes == 0 and p.grants == 0) h.command(); h.die(p); h.complete(); assert(h.writes == 0) end) test("terrain geometry has bounded floor, half steps, doorway, pool, falls and resources", function() local h = harness(); h.load(); h.player(); h.command(); h.complete() assert(h.reads == 41041 and h.writes < 45000) local half = h.registered["hearth:m1_course_half_step"] assert(half.node_box.fixed[2] == -0.5 and half.node_box.fixed[5] == 0) assert(h.node(11,51,5) == "hearth:m1_course_half_step" and h.node(12,51,5) == "hearth:planks") assert(h.node(26,51,5) == "air" and h.node(26,52,5) == "air" and h.node(26,53,5) == "hearth:wall") assert(h.node(26,51,4) == "hearth:wall" and h.node(26,51,6) == "hearth:wall") assert(h.node(39,48,10) == "hearth:stone" and h.node(39,49,10) == "hearth:water_source") assert(h.node(34,49,10) == "hearth:stone" and h.node(34,50,10) == "hearth:water_source") assert(h.node(48,52,7) == "hearth:planks" and h.node(49,51,7) == "air") assert(h.node(60,54,7) == "hearth:planks" and h.node(61,51,7) == "air") assert(h.node(70,51,10) == "hearth:log" and h.node(70,51,12) == "hearth:loose_stone") assert(h.node(82,50,33) == "hearth:planks" and h.node(82,51,33) == "air") assert(h.node(29,52,9) == "air") end) test("optional snag fixture is explicit and bounded", function() local h = harness(); h.settings.hearth_m1_course_snag = true h.load(); h.player(); h.command(); h.complete(); assert(h.node(29,52,9) == "hearth:roof") end) test("staged kit is limited to disposable course and known content names", function() local h = harness(); h.load(); local p = h.player(); h.command(); h.complete() assert(#p.kit == 8 and p.kit[1] == "hearth:axe" and p.kit[2] == "hearth:knife" and p.kit[3] == "hearth:spear") assert(p.kit[4] == "hearth:planks 64" and p.kit[5] == "hearth:wall 64" and p.kit[6] == "hearth:roof 64") end) test("checkpoints progress in order within five nodes, never from mere elapsed time", function() local h = harness(); h.load(); local p = h.player(); h.command(); h.complete() p.pos = {x = 26, y = 50.5, z = 5}; h.tick(1) assert(h.module.report("alice"):find("checkpoints 0/10", 1, true)) p.pos = {x = 20.01, y = 51, z = 5}; h.tick(0.1) assert(h.module.report("alice"):find("checkpoints 0/10", 1, true)) p.pos = {x = 20, y = 51, z = 5}; h.tick(0.1) assert(h.module.report("alice"):find("checkpoints 1/10", 1, true)) local points = {{26,50.5,5},{39,49.5,10},{50,50.5,7},{62,50.5,7},{71,50.5,10}, {79,50.5,20},{82,50.5,33},{60,50.5,33},{8,50.5,33}} for _, v in ipairs(points) do p.pos = {x=v[1],y=v[2],z=v[3]}; h.tick(0.2) end local result = h.module.report("alice"); assert(result:find("complete",1,true) and result:find("checkpoints 10/10",1,true)) h.tick(10); assert(h.module.report("alice") == result) end) test("telemetry uses bounded real step samples with honest p95 labels and retry reset", function() local h = harness(); h.load(); h.player(); h.command(); h.complete() for _ = 1, 650 do h.tick(0.02) end local ok, report = h.command("alice", "report") assert(ok and report:find("p95 20.00ms (last 600 samples)",1,true)) assert(report:find("Not client FPS or CPU profiling",1,true) and report:find("p95 0.00us",1,true)) h.command("alice", "retry"); report = h.module.report("alice") assert(report:find("0.0s; checkpoints 0/10",1,true) and report:find("last 0 samples",1,true)) for _, dt in ipairs({0/0, math.huge, -1, 0}) do h.steps[1](dt) end assert(h.module.report("alice") == report) end) test("leave/death discard telemetry; inactive players get no sampling or grants", function() local h = harness(); h.load(); local a, b = h.player("alice"), h.player("bob") h.command(); h.complete(); h.tick(1) assert(b.grants == 0 and h.module.report("bob"):find("No course run",1,true)) h.die(a); assert(h.module.report("alice"):find("No course run",1,true)) h.command(); h.leave(a); assert(h.module.report("alice"):find("No course run",1,true)) end) test("session count and run duration are bounded", function() local h = harness(); h.load() for i = 1, 16 do h.player("p"..i); assert(h.command("p"..i)) end h.player("overflow"); assert(not h.command("overflow")); h.complete() h.tick(1801); assert(h.module.report("p1"):find("No course run",1,true)) assert(h.command("overflow")) end) print("PASS " .. total .. " course checks")