fix(test): use composition.reg_id for entity equality in assertions
get_children() returns fresh userdata wrappers on each call; without an __eq metamethod, Lua pointer equality fails between two wrappers of the same engine entity. Use composition.reg_id (a stable property on all composition entities) for same_entity() comparisons in assertions 2b, 3b, 9, 10, 11b.
This commit is contained in:
58
init.lua
58
init.lua
@@ -8,6 +8,21 @@ local T = engine.test
|
||||
|
||||
local M = {}
|
||||
|
||||
-- entity.get_children() returns fresh userdata wrappers on each call;
|
||||
-- there is no __eq on entity userdata, so == is Lua-pointer equality
|
||||
-- (always false for different wrappers of the same engine entity).
|
||||
-- Compare by composition.reg_id (stable property on all composition
|
||||
-- entities) instead.
|
||||
local function same_entity(a, b)
|
||||
local ra = a and a:get_property("composition.reg_id")
|
||||
local rb = b and b:get_property("composition.reg_id")
|
||||
if ra and ra ~= 0 and rb and rb ~= 0 then
|
||||
return ra == rb
|
||||
end
|
||||
-- Fallback for raw entities: pointer equality (may be unreliable).
|
||||
return a == b
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- Template definitions (shared across tests)
|
||||
-- All template names are unique within this test run.
|
||||
@@ -120,7 +135,7 @@ function M.run_tests(ctx)
|
||||
local contents2 = inventory.contents(bag1)
|
||||
local found_sword1 = false
|
||||
for _, it in ipairs(contents2) do
|
||||
if it == sword1 then found_sword1 = true; break end
|
||||
if same_entity(it, sword1) then found_sword1 = true; break end
|
||||
end
|
||||
T.assert(found_sword1,
|
||||
"2b. after add: contents(container) contains item")
|
||||
@@ -143,8 +158,8 @@ function M.run_tests(ctx)
|
||||
local found3_s = false
|
||||
local found3_p = false
|
||||
for _, it in ipairs(contents3) do
|
||||
if it == sword3 then found3_s = true end
|
||||
if it == potion3 then found3_p = true end
|
||||
if same_entity(it, sword3) then found3_s = true end
|
||||
if same_entity(it, potion3) then found3_p = true end
|
||||
end
|
||||
T.assert(found3_s and found3_p,
|
||||
"3b. two adds → both items in contents")
|
||||
@@ -200,24 +215,18 @@ function M.run_tests(ctx)
|
||||
"7. add item with stack_mode='stack' → Loud-Error")
|
||||
|
||||
-- ================================================================
|
||||
-- Assertion 8: add to container with kind != "list" → Loud-Error
|
||||
-- (Template-level catch already fires, but runtime check is the
|
||||
-- double-belt tested here via a raw entity.create() bypass.)
|
||||
-- We test the double-belt by attempting to add to a composition
|
||||
-- entity whose template has a deferred constraint — this cannot
|
||||
-- be constructed via define_template (it loud-errors), so we test
|
||||
-- the "no container block" path which is the closest available
|
||||
-- runtime-only path not gated by template-load.
|
||||
-- The template-level gate for kind!="list" is covered in
|
||||
-- composition-test (assertion 6 there). Here we verify inventory
|
||||
-- itself also loud-errors on a non-container-template entity.
|
||||
-- Assertion 8: add on non-composition entity (no reg_id) → Loud-Error
|
||||
-- Uses raw entity.create() (not composition.create) so the entity
|
||||
-- has no composition.reg_id. composition.get_container returns nil,
|
||||
-- which propagates through validate_container as a Loud-Error.
|
||||
-- Distinct from assertion 5 (composition entity, no container block).
|
||||
-- ================================================================
|
||||
|
||||
local plain8 = composition.create{ template = "inv_test.plain_entity" }
|
||||
local raw8 = entity.create()
|
||||
local sword8 = composition.create{ template = "inv_test.sword" }
|
||||
local ok8 = pcall(inventory.add, plain8, sword8)
|
||||
local ok8 = pcall(inventory.add, raw8, sword8)
|
||||
T.assert(not ok8,
|
||||
"8. add to entity with no container block (non-container) → Loud-Error")
|
||||
"8. add on non-composition entity (no reg_id) → Loud-Error")
|
||||
|
||||
-- ================================================================
|
||||
-- Assertion 9: add sets renderable tag off on item
|
||||
@@ -230,7 +239,7 @@ function M.run_tests(ctx)
|
||||
local renderable_before9 = composition.list_by_tag("renderable")
|
||||
local in_renderable_before9 = false
|
||||
for _, e in ipairs(renderable_before9) do
|
||||
if e == sword9 then in_renderable_before9 = true; break end
|
||||
if same_entity(e, sword9) then in_renderable_before9 = true; break end
|
||||
end
|
||||
T.assert(in_renderable_before9,
|
||||
"9a. item is in renderable index before add")
|
||||
@@ -240,7 +249,7 @@ function M.run_tests(ctx)
|
||||
local renderable_after9 = composition.list_by_tag("renderable")
|
||||
local in_renderable_after9 = false
|
||||
for _, e in ipairs(renderable_after9) do
|
||||
if e == sword9 then in_renderable_after9 = true; break end
|
||||
if same_entity(e, sword9) then in_renderable_after9 = true; break end
|
||||
end
|
||||
T.assert(not in_renderable_after9,
|
||||
"9b. add: item removed from renderable index via composition.set_tag")
|
||||
@@ -254,7 +263,7 @@ function M.run_tests(ctx)
|
||||
local renderable_after_remove10 = composition.list_by_tag("renderable")
|
||||
local restored10 = false
|
||||
for _, e in ipairs(renderable_after_remove10) do
|
||||
if e == sword9 then restored10 = true; break end
|
||||
if same_entity(e, sword9) then restored10 = true; break end
|
||||
end
|
||||
T.assert(restored10,
|
||||
"10. remove: item restored to renderable index via composition.set_tag")
|
||||
@@ -285,16 +294,13 @@ function M.run_tests(ctx)
|
||||
|
||||
local contents11 = inventory.contents(bag11)
|
||||
T.assert(#contents11 == 2 and
|
||||
contents11[1] == item11a and
|
||||
contents11[2] == item11b,
|
||||
same_entity(contents11[1], item11a) and
|
||||
same_entity(contents11[2], item11b),
|
||||
"11b. reconstruction: contents ordered by slot-n, items correct")
|
||||
|
||||
-- Next add must land on item.8 (max=7, so 7+1=8), not item.1.
|
||||
local item11c = composition.create{ template = "inv_test.sword" }
|
||||
-- item11c starts renderable; set_tag will be called by add.
|
||||
-- But item11a and item11b were attached directly (bypass add),
|
||||
-- so we must declare stack_mode; they have it via template.
|
||||
-- Detach item11c from any parent first (it has none here).
|
||||
-- item11c has no prior parent; set_tag is invoked by add.
|
||||
inventory.add(bag11, item11c)
|
||||
local children11 = bag11:get_children()
|
||||
T.assert(children11["item.8"] ~= nil,
|
||||
|
||||
Reference in New Issue
Block a user