|
|
|
@@ -357,6 +357,179 @@ function M.run_tests(ctx)
|
|
|
|
-- Cleanup
|
|
|
|
-- Cleanup
|
|
|
|
os.remove(out_path); os.remove(out_path_2); os.remove(abs_rl_path)
|
|
|
|
os.remove(out_path); os.remove(out_path_2); os.remove(abs_rl_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- =====================================================================
|
|
|
|
|
|
|
|
-- 0.5.7: Cell-Tile material API tests (maps_t1)
|
|
|
|
|
|
|
|
-- =====================================================================
|
|
|
|
|
|
|
|
-- Reload the write_test map for a clean slate.
|
|
|
|
|
|
|
|
maps.set_current("write_test")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- maps_t1: round-trip set/get
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 1, 1, true)
|
|
|
|
|
|
|
|
engine.test.equals(maps.get_cell_material("surface", 1, 1), true,
|
|
|
|
|
|
|
|
"maps_t1: set_cell_material then get_cell_material round-trips")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 1, 1, false)
|
|
|
|
|
|
|
|
engine.test.equals(maps.get_cell_material("surface", 1, 1), false,
|
|
|
|
|
|
|
|
"maps_t1: set_cell_material(false) clears the flag")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Out-of-bounds rejection
|
|
|
|
|
|
|
|
local ok_oob, err_oob = pcall(function()
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", -1, 0, true)
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
engine.test.assert(not ok_oob,
|
|
|
|
|
|
|
|
"maps_t1: set_cell_material rejects negative x")
|
|
|
|
|
|
|
|
engine.test.assert(err_oob and err_oob:find("bounds"),
|
|
|
|
|
|
|
|
"maps_t1: bounds-error mentions 'bounds'")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Unknown-layer rejection
|
|
|
|
|
|
|
|
local ok_lay = pcall(function()
|
|
|
|
|
|
|
|
maps.set_cell_material("bogus_layer", 0, 0, true)
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
engine.test.assert(not ok_lay,
|
|
|
|
|
|
|
|
"maps_t1: set_cell_material rejects unknown layer")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- =====================================================================
|
|
|
|
|
|
|
|
-- maps_t2-t7: Cell-Tile slot-resolution proofs
|
|
|
|
|
|
|
|
-- =====================================================================
|
|
|
|
|
|
|
|
-- write_test is 4x4. Use v2_size for w/h reference (already declared earlier).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- maps_t2: cell_material_slot returns a non-nil record for a
|
|
|
|
|
|
|
|
-- cells_material cell.
|
|
|
|
|
|
|
|
-- Clear the surface layer's cells_material first.
|
|
|
|
|
|
|
|
for cy = 0, v2_size.h - 1 do
|
|
|
|
|
|
|
|
for cx = 0, v2_size.w - 1 do
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", cx, cy, false)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 1, 1, true)
|
|
|
|
|
|
|
|
local rec = maps.cell_material_slot("surface", 1, 1)
|
|
|
|
|
|
|
|
engine.test.assert(rec ~= nil,
|
|
|
|
|
|
|
|
"maps_t2: cell_material_slot returns non-nil for cell-tile material")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- maps_t3: isolated slot reachable for the first time.
|
|
|
|
|
|
|
|
-- Clear cells_material AND vertices, place an isolated paint at (2, 2).
|
|
|
|
|
|
|
|
for cy = 0, v2_size.h - 1 do
|
|
|
|
|
|
|
|
for cx = 0, v2_size.w - 1 do
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", cx, cy, false)
|
|
|
|
|
|
|
|
maps.set_vertex("surface", cx, cy, false)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
maps.set_vertex("surface", v2_size.w, cy, false)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
for cx = 0, v2_size.w do maps.set_vertex("surface", cx, v2_size.h, false) end
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 2, 2, true)
|
|
|
|
|
|
|
|
local r3 = maps.cell_material_slot("surface", 2, 2)
|
|
|
|
|
|
|
|
engine.test.equals(r3.slot, 0, "maps_t3: slot 0 isolated reachable for first time")
|
|
|
|
|
|
|
|
engine.test.equals(r3.rot, 0, "maps_t3: isolated rot=0")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- maps_t4: two adjacent cells → two end-caps facing each other.
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 1, 2, true)
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 2, 2, true)
|
|
|
|
|
|
|
|
local r4a = maps.cell_material_slot("surface", 1, 2)
|
|
|
|
|
|
|
|
local r4b = maps.cell_material_slot("surface", 2, 2)
|
|
|
|
|
|
|
|
engine.test.equals(r4a.slot, 1, "maps_t4: left cell is end (slot 1)")
|
|
|
|
|
|
|
|
engine.test.equals(r4a.rot, 1, "maps_t4: left end points east (rot 1)")
|
|
|
|
|
|
|
|
engine.test.equals(r4b.slot, 1, "maps_t4: right cell is end (slot 1)")
|
|
|
|
|
|
|
|
engine.test.equals(r4b.rot, 3, "maps_t4: right end points west (rot 3)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- maps_t5: 3-cell line → middle is straight.
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 0, 2, true)
|
|
|
|
|
|
|
|
-- already painted (1,2) and (2,2) from t4
|
|
|
|
|
|
|
|
local r5 = maps.cell_material_slot("surface", 1, 2)
|
|
|
|
|
|
|
|
engine.test.equals(r5.slot, 4, "maps_t5: middle of 3-cell line is straight (slot 4)")
|
|
|
|
|
|
|
|
-- rot may be 1 or 3 (horizontal canonical); accept both
|
|
|
|
|
|
|
|
engine.test.assert(r5.rot == 1 or r5.rot == 3,
|
|
|
|
|
|
|
|
"maps_t5: straight is horizontal (rot 1 or 3)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Reset surface for t6.
|
|
|
|
|
|
|
|
for cx = 0, v2_size.w - 1 do
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", cx, 2, false)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- maps_t6: T-junction at (1, 2) with arms W (0, 2), E (2, 2), S (1, 3).
|
|
|
|
|
|
|
|
-- write_test is 4x4 so (1, 3) is the last row.
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 0, 2, true)
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 1, 2, true)
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 2, 2, true)
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 1, 3, true)
|
|
|
|
|
|
|
|
local r6 = maps.cell_material_slot("surface", 1, 2)
|
|
|
|
|
|
|
|
engine.test.equals(r6.slot, 5, "maps_t6: T-junction is tee_open (slot 5)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Reset for t7.
|
|
|
|
|
|
|
|
for cy = 0, v2_size.h - 1 do
|
|
|
|
|
|
|
|
for cx = 0, v2_size.w - 1 do
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", cx, cy, false)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- maps_t7: 4-cell "+" at (1, 1) with N (1, 0), E (2, 1), S (1, 2), W (0, 1).
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 1, 1, true)
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 1, 0, true)
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 2, 1, true)
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 1, 2, true)
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 0, 1, true)
|
|
|
|
|
|
|
|
local r7 = maps.cell_material_slot("surface", 1, 1)
|
|
|
|
|
|
|
|
engine.test.equals(r7.slot, 8, "maps_t7: cross is cross_open (slot 8) — second previously-unreachable slot reachable")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Reset surface fully so later tests (if any added) start clean.
|
|
|
|
|
|
|
|
for cy = 0, v2_size.h - 1 do
|
|
|
|
|
|
|
|
for cx = 0, v2_size.w - 1 do
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", cx, cy, false)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- =====================================================================
|
|
|
|
|
|
|
|
-- maps_t8: cells_material round-trips through save_to_disk + reload
|
|
|
|
|
|
|
|
-- =====================================================================
|
|
|
|
|
|
|
|
-- Use a unique temp path so we don't collide with the earlier write_test save.
|
|
|
|
|
|
|
|
local cm_path = tmp_dir .. "/" .. tmp_suffix .. "_cm.json"
|
|
|
|
|
|
|
|
local lib_dir2 = engine.module.dir_of("lib-core.maps-test")
|
|
|
|
|
|
|
|
local cm_rl_abs = lib_dir2 .. "/maps/write_test_cm_reloaded.map.json"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maps.set_current("write_test")
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", 2, 1, true)
|
|
|
|
|
|
|
|
maps.save_to_disk("write_test", cm_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local f = io.open(cm_path, "r")
|
|
|
|
|
|
|
|
local cm_bytes = f:read("*a"); f:close()
|
|
|
|
|
|
|
|
engine.test.assert(cm_bytes:find('"cells_material"') ~= nil,
|
|
|
|
|
|
|
|
"maps_t8: cells_material appears in serialized JSON when set")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Patch id + relocate so the load resolver can find it.
|
|
|
|
|
|
|
|
local cm_rewritten = cm_bytes:gsub('"id"%s*:%s*"write_test"',
|
|
|
|
|
|
|
|
'"id":"write_test_cm_reloaded"')
|
|
|
|
|
|
|
|
local rf = io.open(cm_rl_abs, "w"); rf:write(cm_rewritten); rf:close()
|
|
|
|
|
|
|
|
maps.load("maps/write_test_cm_reloaded.map.json")
|
|
|
|
|
|
|
|
engine.test.equals(maps.get_cell_material("surface", 2, 1, "write_test_cm_reloaded"), true,
|
|
|
|
|
|
|
|
"maps_t8: cells_material round-trips through save+load")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Cleanup
|
|
|
|
|
|
|
|
os.remove(cm_path); os.remove(cm_rl_abs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- =====================================================================
|
|
|
|
|
|
|
|
-- maps_t9: byte-determinism regression — a map with no cells_material
|
|
|
|
|
|
|
|
-- writes byte-identical output through the 0.5.7 serializer as it did
|
|
|
|
|
|
|
|
-- under 0.5.6.
|
|
|
|
|
|
|
|
-- =====================================================================
|
|
|
|
|
|
|
|
-- Reset surface cells_material so the save contains no cell-tile data.
|
|
|
|
|
|
|
|
maps.set_current("write_test")
|
|
|
|
|
|
|
|
for cy = 0, v2_size.h - 1 do
|
|
|
|
|
|
|
|
for cx = 0, v2_size.w - 1 do
|
|
|
|
|
|
|
|
maps.set_cell_material("surface", cx, cy, false)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local bytes_a_path = tmp_dir .. "/" .. tmp_suffix .. "_a.json"
|
|
|
|
|
|
|
|
local bytes_b_path = tmp_dir .. "/" .. tmp_suffix .. "_b.json"
|
|
|
|
|
|
|
|
maps.save_to_disk("write_test", bytes_a_path)
|
|
|
|
|
|
|
|
maps.save_to_disk("write_test", bytes_b_path)
|
|
|
|
|
|
|
|
local fa = io.open(bytes_a_path, "r"); local bytes_a = fa:read("*a"); fa:close()
|
|
|
|
|
|
|
|
local fb = io.open(bytes_b_path, "r"); local bytes_b = fb:read("*a"); fb:close()
|
|
|
|
|
|
|
|
engine.test.equals(bytes_a, bytes_b,
|
|
|
|
|
|
|
|
"maps_t9: byte-deterministic save with no cells_material content")
|
|
|
|
|
|
|
|
engine.test.assert(bytes_a:find('"cells_material"') == nil,
|
|
|
|
|
|
|
|
"maps_t9: cells_material key absent when all entries are zero")
|
|
|
|
|
|
|
|
os.remove(bytes_a_path); os.remove(bytes_b_path)
|
|
|
|
|
|
|
|
|
|
|
|
engine.exit(engine.test.failures())
|
|
|
|
engine.exit(engine.test.failures())
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|