cc-libs/tests/eventloop.lua
2026-06-08 04:23:31 +02:00

181 lines
4.2 KiB
Lua

-- Eventloop behavior tests for the CraftOS-PC harness.
-- Invoked via `craftos --headless --script tests/eventloop.lua` from `just test`.
local createEventLoop = require('/apis/eventloop');
local createLibTest = require('/apis/libtest');
local testlib = createLibTest({ ... });
testlib.test('register dispatches queued event args', function()
local events = createEventLoop();
local called = 0;
events.register('eventloop_test_basic', function(a, b)
called = called + 1;
testlib.assertEquals(a, 'first');
testlib.assertEquals(b, 42);
events.stopLoop();
end);
os.queueEvent('eventloop_test_basic', 'first', 42);
events.runLoop();
testlib.assertEquals(called, 1);
testlib.assertTrue(not events.isRunningLoop());
end);
testlib.test('STOP unregisters handler after first call', function()
local events = createEventLoop();
local stoppedHandlerCalls = 0;
local observerCalls = 0;
events.register('eventloop_test_stop', function()
stoppedHandlerCalls = stoppedHandlerCalls + 1;
return events.STOP;
end);
events.register('eventloop_test_stop', function()
observerCalls = observerCalls + 1;
if observerCalls == 1 then
os.queueEvent('eventloop_test_stop');
else
events.stopLoop();
end
end);
os.queueEvent('eventloop_test_stop');
events.runLoop();
testlib.assertEquals(stoppedHandlerCalls, 1);
testlib.assertEquals(observerCalls, 2);
end);
testlib.test('manual unregister prevents dispatch', function()
local events = createEventLoop();
local called = 0;
local dispose = events.register('eventloop_test_unregister', function()
called = called + 1;
end);
events.setTimeout(function()
events.stopLoop();
end, 0);
dispose();
os.queueEvent('eventloop_test_unregister');
events.runLoop();
testlib.assertEquals(called, 0);
end);
testlib.test('setTimeout before runLoop fires once', function()
local events = createEventLoop();
local called = 0;
events.setTimeout(function()
called = called + 1;
events.stopLoop();
end, 0);
events.runLoop();
testlib.assertEquals(called, 1);
end);
testlib.test('setTimeout during runLoop fires after event handler', function()
local events = createEventLoop();
local order = '';
events.register('eventloop_test_runtime_timeout', function()
order = order .. 'event>';
events.setTimeout(function()
order = order .. 'timeout';
events.stopLoop();
end, 0);
return events.STOP;
end);
os.queueEvent('eventloop_test_runtime_timeout');
events.runLoop();
testlib.assertEquals(order, 'event>timeout');
end);
testlib.test('cleared timeout before runLoop does not fire', function()
local events = createEventLoop();
local called = 0;
local clear = events.setTimeout(function()
called = called + 1;
end, 0);
clear();
events.setTimeout(function()
events.stopLoop();
end, 0);
events.runLoop();
testlib.assertEquals(called, 0);
end);
testlib.test('onStart and onStop run around loop', function()
local events = createEventLoop();
local order = '';
events.onStart(function()
order = order .. 'start>';
end);
events.onStop(function()
order = order .. 'stop';
end);
events.setTimeout(function()
order = order .. 'timeout>';
events.stopLoop();
end, 0);
events.runLoop();
testlib.assertEquals(order, 'start>timeout>stop');
end);
testlib.test('empty loop returns and runs onStop', function()
local events = createEventLoop();
local stopped = false;
events.onStop(function()
stopped = true;
end);
events.runLoop();
testlib.assertTrue(stopped);
testlib.assertTrue(not events.isRunningLoop());
end);
testlib.test('error contracts are enforced', function()
local events = createEventLoop();
local function handler()
end
events.register('eventloop_test_errors', handler);
testlib.assertErrors(function()
events.register('eventloop_test_errors', handler);
end, 'handler already registered');
testlib.assertErrors(function()
events.stopLoop();
end, 'loop is already stopped');
testlib.assertErrors(function()
events.register(1, handler);
end, 'string expected');
testlib.assertErrors(function()
events.register('eventloop_test_errors_2', 'not a function');
end, 'function expected');
end);
testlib.run();