diff --git a/lib/utils/counter.lua b/lib/utils/counter.lua index 9e8273f..5f75337 100644 --- a/lib/utils/counter.lua +++ b/lib/utils/counter.lua @@ -4,6 +4,7 @@ --- @field private isAlive boolean --- @field push fun():nil добавить 1 к счетчику --- @field pop fun():nil убавить 1 у счетчика +--- @field set fun(count: integer): nil установить значение на счетчике local counter = {} counter.__index = counter @@ -31,6 +32,7 @@ local function new(onFinish) } t.push = function() counter._push(t) end t.pop = function() counter._pop(t) end + t.set = function(count) t.count = count end return setmetatable(t, counter) end diff --git a/lib/utils/task.lua b/lib/utils/task.lua index a64ba49..009f0e7 100644 --- a/lib/utils/task.lua +++ b/lib/utils/task.lua @@ -34,3 +34,33 @@ --- ``` --- @generic T --- @alias Task fun(callback: fun(value: T): nil): nil + +--- Возвращает новый Task, который завершится после завершения всех переданных `tasks`. +--- +--- Значение созданного Task будет содержать список значений `tasks` в том же порядке. +--- +--- См. также https://api.dart.dev/dart-async/Future/wait.html +--- @generic T +--- @param tasks Task[] +--- @return Task +local function wait(tasks) + local count = #tasks + local results = {} + + return function(callback) + for i, task in ipairs(tasks) do + task( + function(result) + results[i] = result + + count = count - 1 + if count == 0 then callback(results) end + end + ) + end + end +end + +return { + wait = wait, +} diff --git a/main.lua b/main.lua index b2f120c..b5064d8 100644 --- a/main.lua +++ b/main.lua @@ -2,6 +2,8 @@ local character = require "lib/character/character" local testLayout +local TestRunner = require "test.runner" +TestRunner:register(require "test.task") function love.conf(t) t.console = true @@ -67,6 +69,8 @@ end local lt = "0" function love.update(dt) + TestRunner:update(dt) -- закомментировать для отключения тестов + local t1 = love.timer.getTime() Tree.controls:poll() Tree.level.camera:update(dt) -- сначала логика камеры, потому что на нее завязан UI diff --git a/test/runner.lua b/test/runner.lua new file mode 100644 index 0000000..e865e1e --- /dev/null +++ b/test/runner.lua @@ -0,0 +1,46 @@ +--- @class Test +local test = {} +function test:run(complete) end + +function test:update(dt) end + +--- @class TestRunner +--- @field private tests Test[] +--- @field private state "loading" | "running" | "completed" +--- @field private completedCount integer +local runner = {} +runner.tests = {} +runner.state = "loading" +runner.completedCount = 0 + +--- глобальный update для тестов, нужен для тестирования фич, зависимых от времени +function runner:update(dt) + if self.state == "loading" then + print("[TestRunner]: running " .. #self.tests .. " tests") + + for _, t in ipairs(self.tests) do + t:run( + function() + self.completedCount = self.completedCount + 1 + if self.completedCount == #self.tests then + self.state = "completed" + print("[TestRunner]: tests completed") + end + end + ) + end + self.state = "running" + end + + for _, t in ipairs(self.tests) do + if t.update then t:update(dt) end + end +end + +--- добавляет тест для прохождения +--- @param t Test +function runner:register(t) + table.insert(self.tests, t) +end + +return runner diff --git a/test/task.lua b/test/task.lua new file mode 100644 index 0000000..93908bf --- /dev/null +++ b/test/task.lua @@ -0,0 +1,61 @@ +local task = require "lib.utils.task" + +local test = {} + +local t0 +local task1Start, task2Start +local task1Callback, task2Callback + +--- @return Task +local function task1() + return function(callback) + task1Start = love.timer.getTime() + task1Callback = callback + end +end + +--- @return Task +local function task2() + return function(callback) + task2Start = love.timer.getTime() + task2Callback = callback + end +end + +function test:run(complete) + t0 = love.timer.getTime() + + task.wait { + task1(), + task2() + } (function(values) + local tWait = love.timer.getTime() + local dt = tWait - t0 + + local t1 = values[1] + local t2 = values[2] + + assert(type(t1) == "number" and type(t2) == "number") + assert(t2 > t1) + assert(dt >= 2, "dt = " .. dt) + + print("task.wait completed in " .. dt .. " sec", "t1 = " .. t1 - t0, "t2 = " .. t2 - t0) + + complete() + end) +end + +function test:update(dt) + local t = love.timer.getTime() + if task1Start and t - task1Start >= 1 then + task1Callback(t) + task1Start = nil + end + + if task2Start and t - task2Start >= 2 then + task2Callback(t) + task2Start = nil + end +end + +return test