local testCount = 0 local failCount = 0 local function test(msg, f) testCount = testCount + 1 local success, error = xpcall(f, debug.traceback) if success then print(msg .. "\t\t[OK]") else failCount = failCount + 1 print(msg .. "\t\t[FAIL]") print(error) end end local ecs = require 'ecs' --===== Component tests =====-- local Component = ecs.Component test("factories work as expected", function() local factory = Component.newFactory("health", { percent=100 }) local comp1 = factory() assert(comp1.__type == "health", "bad component type for comp1") assert(comp1.percent == 100, "bat percent for comp1") local comp2 = factory{ percent=50 } assert(comp2.__type == "health", "bad component type for comp2") assert(comp2.percent == 50, "bad percent for comp2") local success = pcall(function() comp2.dne = 5 end) assert(not success, "incorrectly succeeded in setting comp2.dne") local success = pcall(function() local comp3 = factory{ percent = 44, something = 2 } end) assert(not success, "incorrectly succeeded in creating comp3") end) test("components serialize as expected", function() local position = Component.newFactory("position", { x=0, y=0, z=0 }) local comp = position{x=10, y=15, z=10} local str = tostring(comp) local tbl = (loadstring("return " .. str))() assert(tbl.__type == "position", "bad type") assert(tbl.x == 10, "bad x") assert(tbl.y == 15, "bad y") assert(tbl.z == 10, "bad z") end) test("components serialize successfully with subcomponents", function() local position = Component.newFactory("position", { x=0, y=0, z=0 }) local player = Component.newFactory("player", { name="", position={} }) local p = player{ name="hannah", position=position{x=10, y=9, z=8} } local tbl = (loadstring("return " .. tostring(p)))() assert(tbl.__type == "player") assert(tbl.name == "hannah") assert(tbl.position.__type == "position") assert(tbl.position.x == 10) assert(tbl.position.y == 9) assert(tbl.position.z == 8) end) --===== EntityDb tests =====-- local EntityDb = ecs.EntityDb test("EntityDb.createEntity() always returns a new id", function() local db = EntityDb() local ids = {} for i=1,100 do local id = db:createEntity() assert(ids[id] == nil, "id was already returned!") ids[id] = true end end) test("EntityDb.queryComponent() gets all entities with a given component", function() local db = EntityDb() local ids = {} for i=1,100 do local id = db:createEntity() if i%2==0 then ids[id] = 5*i db:addComponent(id, "number", 5*i) end end local query = db:queryComponent("number") local count = 0 for id, number in pairs(query) do count = count + 1 assert(number == ids[id]) end assert(count == 50) end) test("EntityDb.queryEntity() gets all components associated with an entity", function() local db = EntityDb() local entity for i=1,100 do local id = db:createEntity() if i%2 == 0 then db:addComponent(id, "number", 2) end if i%3 == 0 then db:addComponent(id, "string", "hello") end if i%5 == 0 then db:addComponent(id, "number2", 4) end if i%7 == 0 then db:addComponent(id, "string2", "world") end if i == 30 then entity=id end end local query = db:queryEntity(entity) assert(query.number == 2) assert(query.string == "hello") assert(query.number2 == 4) assert(query.string2 == nil) end) test("EntityDb.removeComponent() removes components correctly", function() local db = EntityDb() local id = db:createEntity() db:addComponent(id, "number", 2) db:addComponent(id, "string", "hello") db:addComponent(id, "number2", 4) db:addComponent(id, "string2", "world") local query = db:queryEntity(id) assert(query.number == 2) assert(query.string == "hello") assert(query.number2 == 4) assert(query.string2 == "world") db:removeComponent(id, "string2") query = db:queryEntity(id) assert(query.number == 2) assert(query.string == "hello") assert(query.number2 == 4) assert(query.string2 == nil) db:removeComponent(id, "number2") query = db:queryEntity(id) assert(query.number == 2) assert(query.string == "hello") assert(query.number2 == nil) assert(query.string2 == nil) db:removeComponent(id, "string") query = db:queryEntity(id) assert(query.number == 2) assert(query.string == nil) assert(query.number2 == nil) assert(query.string2 == nil) db:removeComponent(id, "number") query = db:queryEntity(id) assert(query.number == nil) assert(query.string == nil) assert(query.number2 == nil) assert(query.string2 == nil) end) test("EntityDb.removeComponent() deletes component table when empty", function() local db = EntityDb() local id1 = db:createEntity() local id2 = db:createEntity() db:addComponent(id1, "number", 2) db:addComponent(id2, "number", 3) assert(db.components.number ~= nil) db:removeComponent(id1, "number") assert(db.components.number ~= nil) db:removeComponent(id2, "number") assert(db.components.number == nil) end) test("EntityDb.removeComponent() does nothing if the component is not present", function() local db = EntityDb() local id1 = db:createEntity() local id2 = db:createEntity() db:addComponent(id1, "number", 2) db:addComponent(id2, "number", 3) assert(db.components.number ~= nil) db:removeComponent(id1, "number") assert(db.components.number ~= nil) db:removeComponent(id1, "number") assert(db.components.number ~= nil) db:removeComponent(id2, "number") assert(db.components.number == nil) end) test("EntityDb.deleteEntity() correctly removes an entity", function() local db = EntityDb() local id1 = db:createEntity() local id2 = db:createEntity() db:addComponent(id1, "number", 2) db:addComponent(id2, "number", 3) local query = db:queryComponent("number") assert(query[id1] and query[id2]) db:deleteEntity(id1) query = db:queryComponent("number") assert(query[id1] == nil) assert(query[id2] ~= nil) assert(false == pcall(function() local query = db:queryEntity(id1) end)) end) --===== SystemDb tests =====-- local SystemDb = ecs.SystemDb test("addSystem() correctly sorts systems", function() local sdb = SystemDb(nil) local str = "" sdb:addSystem(function () return { update=function(self, dt) str = str .. "c" end, priority = 3, } end) sdb:addSystem{ update=function(self, dt) str = "a" end, priority = 1, } sdb:addSystem{ update=function(self, dt) str = str .. "b" end, priority = 2, } sdb:update(0) assert(str == "abc") end) test("removeSystem() correctly handles things", function() local sdb = SystemDb(nil) local str = "" sdb:addSystem(function () return { update=function(self, dt) str = str .. "c" end, priority = 3, } end) sdb:addSystem{ update=function(self, dt) str = "a" end, priority = 1, } local id = sdb:addSystem{ update=function(self, dt) str = str .. "b" end, priority = 2, } sdb:update(0) assert(str == "abc") sdb:removeSystem(id) sdb:update(1) assert(str == "ac") end) print(string.format("ran %d tests, %d failed", testCount, failCount))