diff --git a/src/action-queue.lua b/src/action-queue.lua index efe6956..f9e2677 100644 --- a/src/action-queue.lua +++ b/src/action-queue.lua @@ -1,5 +1,6 @@ +---@class ActionQueue +---@field queue table actionQueue = { - ---@type table queue = {}, } @@ -52,3 +53,8 @@ function actionQueue:runWaiting(deltaSeconds) end end end + +-- luacheck: ignore +if not playdate or playdate.TEST_MODE then + return actionQueue +end diff --git a/src/test/mocks.lua b/src/test/mocks.lua index 1fca7ad..8ec6658 100644 --- a/src/test/mocks.lua +++ b/src/test/mocks.lua @@ -1,7 +1,16 @@ utils = require("utils") +local currentTimeMs = 0 + local mockPlaydate = { TEST_MODE = true, + skipMs = function(skip) + currentTimeMs = currentTimeMs + skip + end, + getCurrentTimeMilliseconds = function() + currentTimeMs = currentTimeMs + 1 + return currentTimeMs + end, timer = { new = function(_, callback) return { diff --git a/src/test/testActionQueue.lua b/src/test/testActionQueue.lua new file mode 100644 index 0000000..433a2f2 --- /dev/null +++ b/src/test/testActionQueue.lua @@ -0,0 +1,87 @@ +require("test/setup") +require("action-queue") + +function testActionQueueRunsToCompletion() + actionQueue.queue = {} + local invokeTotalSec = 0 + local hasYielded = false + actionQueue:upsert("testAction", 9999999999, function(delta) + while invokeTotalSec < 5 do + invokeTotalSec = invokeTotalSec + delta + hasYielded = true + coroutine.yield() + end + end) + luaunit.assertIsFalse(hasYielded, "Should not have been invoked yet.") + for _ = 1, 10 do + actionQueue:runWaiting(1) + luaunit.assertIsTrue(hasYielded, "Should have been invoked.") + end + luaunit.assertEquals(5, invokeTotalSec, "Should have run five times and stopped itself") +end + +function testActionQueueExpiration() + actionQueue.queue = {} + local yieldCount = 0 + actionQueue:upsert("testAction", 2000, function(delta) + while true do + yieldCount = yieldCount + 1 + coroutine.yield() + end + end) + + local skipSec = 60 + playdate.skipMs(60 * 1000) + actionQueue:runWaiting(skipSec) + luaunit.assertEquals(1, yieldCount, "Should always be invoked at least once") + + playdate.skipMs(1000) + actionQueue:runWaiting(1) + luaunit.assertEquals(1, yieldCount, "Should not be invoked again after expiry") +end + +function testDuplicateUpsertsShouldOnlyRunOnce() + actionQueue.queue = {} + local yieldCount = 0 + local yieldId + local action = function(id) + return function() + while true do + yieldCount = yieldCount + 1 + yieldId = id + coroutine.yield() + end + end + end + + for i = 1, 10 do + actionQueue:upsert("testAction", 9999999999, action(i)) + end + actionQueue:runWaiting(1) + luaunit.assertEquals(1, yieldCount, "Duplicate upserts should result in only one invocation.") + luaunit.assertEquals(10, yieldId, "Most recent upsert should take precedence.") +end + +function testNewOnlyActionsShouldNotReplaceExistingActions() + actionQueue.queue = {} + local yieldCount = 0 + local yieldId + local action = function(id) + return function() + while true do + yieldCount = yieldCount + 1 + yieldId = id + coroutine.yield() + end + end + end + + for i = 1, 10 do + actionQueue:newOnly("testAction", 9999999999, action(i)) + end + actionQueue:runWaiting(1) + luaunit.assertEquals(1, yieldCount, "Duplicate newOnly should result in only one invocation.") + luaunit.assertEquals(1, yieldId, "The first newOnly should take precedence.") +end + +os.exit(luaunit.LuaUnit.run())