diff --git a/init.lua b/init.lua index 19ec30b..519698a 100644 --- a/init.lua +++ b/init.lua @@ -300,6 +300,63 @@ function M.run_tests(ctx) 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") + -- ---------- 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()) end