summaryrefslogtreecommitdiff
path: root/honey/ecs/ecs.test.lua
diff options
context:
space:
mode:
Diffstat (limited to 'honey/ecs/ecs.test.lua')
-rw-r--r--honey/ecs/ecs.test.lua280
1 files changed, 280 insertions, 0 deletions
diff --git a/honey/ecs/ecs.test.lua b/honey/ecs/ecs.test.lua
new file mode 100644
index 0000000..74e27dc
--- /dev/null
+++ b/honey/ecs/ecs.test.lua
@@ -0,0 +1,280 @@
+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))