Add save_to_disk round-trip and determinism asserts
Verifies the saved JSON is readable, that two successive saves produce byte-identical output, and that re-loading the saved file recovers the same cell values that were written before saving. Uses engine.module.dir_of to write the round-trip fixture to the lib maps/ directory (asset sandbox rejects absolute temp paths).
This commit is contained in:
57
init.lua
57
init.lua
@@ -300,6 +300,63 @@ function M.run_tests(ctx)
|
|||||||
local ok_b = pcall(function() maps.set_roof(4, 0, 1) end)
|
local ok_b = pcall(function() maps.set_roof(4, 0, 1) end)
|
||||||
engine.test.assert(not ok_b, "set_roof rejects x out of bounds")
|
engine.test.assert(not ok_b, "set_roof rejects x out of bounds")
|
||||||
|
|
||||||
|
-- ---------- v0.4.0: save_to_disk ----------
|
||||||
|
-- Map state from Task 1+2: surface(1,2) = gid_painted, wall(2,2) = gid_painted,
|
||||||
|
-- roof(2,2) = 1. Save and re-load to verify round-trip.
|
||||||
|
|
||||||
|
-- Re-establish deterministic state (defensive — earlier asserts may have toggled).
|
||||||
|
maps.set_cell_gid("surface", 1, 2, gid_painted)
|
||||||
|
maps.set_cell_gid("wall", 2, 2, gid_painted)
|
||||||
|
maps.set_roof(2, 2, 1)
|
||||||
|
|
||||||
|
-- Pick a temp path. Use TEMP env var for Windows compatibility; fall back to
|
||||||
|
-- os.tmpname() on POSIX (where it returns a writable path).
|
||||||
|
local tmp_dir = os.getenv("TEMP") or os.getenv("TMP") or "/tmp"
|
||||||
|
-- Unique suffix via os.clock() + os.time() to avoid collisions.
|
||||||
|
local tmp_suffix = string.format("sporel_maps_test_%d_%d", os.time(), math.floor(os.clock() * 1e6) % 1000000)
|
||||||
|
local out_path = tmp_dir .. "/" .. tmp_suffix .. "_1.json"
|
||||||
|
local out_path_2 = tmp_dir .. "/" .. tmp_suffix .. "_2.json"
|
||||||
|
local rl_path = tmp_dir .. "/" .. tmp_suffix .. "_rl.json"
|
||||||
|
maps.save_to_disk("write_test", out_path)
|
||||||
|
|
||||||
|
-- Re-read raw bytes for byte-determinism test
|
||||||
|
local f1 = io.open(out_path, "r")
|
||||||
|
engine.test.assert(f1 ~= nil, "save_to_disk wrote a readable file")
|
||||||
|
local bytes_1 = f1:read("*a")
|
||||||
|
f1:close()
|
||||||
|
|
||||||
|
-- Save a second time; bytes must match exactly
|
||||||
|
maps.save_to_disk("write_test", out_path_2)
|
||||||
|
local f2 = io.open(out_path_2, "r")
|
||||||
|
local bytes_2 = f2:read("*a")
|
||||||
|
f2:close()
|
||||||
|
engine.test.equals(bytes_1, bytes_2,
|
||||||
|
"save_to_disk is byte-deterministic across calls")
|
||||||
|
|
||||||
|
-- Verify JSON has expected keys
|
||||||
|
engine.test.assert(bytes_1:find('"schema_version"') ~= nil, "saved file has schema_version key")
|
||||||
|
engine.test.assert(bytes_1:find('"surface"') ~= nil, "saved file has surface key")
|
||||||
|
engine.test.assert(bytes_1:find('"wall"') ~= nil, "saved file has wall key (auto-allocated)")
|
||||||
|
engine.test.assert(bytes_1:find('"roof"') ~= nil, "saved file has roof key (set in Task 2)")
|
||||||
|
|
||||||
|
-- Re-load (with patched id to avoid registry collision).
|
||||||
|
-- engine.asset.load_json only accepts relative (sandboxed) paths, so write
|
||||||
|
-- the round-trip file into the maps-test lib's own maps/ directory where
|
||||||
|
-- the asset resolver can find it by relative path.
|
||||||
|
local lib_dir = engine.module.dir_of("lib-core.maps-test")
|
||||||
|
local rewritten = bytes_1:gsub('"id"%s*:%s*"write_test"', '"id":"write_test_reloaded"')
|
||||||
|
local abs_rl_path = lib_dir .. "/maps/write_test_reloaded.map.json"
|
||||||
|
local rf = io.open(abs_rl_path, "w"); rf:write(rewritten); rf:close()
|
||||||
|
maps.load("maps/write_test_reloaded.map.json")
|
||||||
|
|
||||||
|
engine.test.equals(maps.cell_gid("surface", 1, 2, "write_test_reloaded"), gid_painted,
|
||||||
|
"save round-trip preserves surface cell")
|
||||||
|
engine.test.equals(maps.cell_gid("wall", 2, 2, "write_test_reloaded"), gid_painted,
|
||||||
|
"save round-trip preserves wall cell")
|
||||||
|
|
||||||
|
-- Cleanup
|
||||||
|
os.remove(out_path); os.remove(out_path_2); os.remove(abs_rl_path)
|
||||||
|
|
||||||
engine.exit(engine.test.failures())
|
engine.exit(engine.test.failures())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user