Current section
Files
Jump to
Current section
Files
test/py_erlang_sleep_SUITE.erl
%% @doc Tests for Erlang sleep fast path (erlang_asyncio module).
%%
%% Tests the _erlang_sleep NIF and erlang_asyncio Python module.
-module(py_erlang_sleep_SUITE).
-include_lib("common_test/include/ct.hrl").
-export([all/0, init_per_suite/1, end_per_suite/1]).
-export([
test_erlang_sleep_available/1,
test_erlang_sleep_basic/1,
test_erlang_sleep_zero/1,
test_erlang_sleep_accuracy/1,
test_erlang_asyncio_module/1,
test_erlang_asyncio_gather/1,
test_erlang_asyncio_wait_for/1,
test_erlang_asyncio_create_task/1
]).
all() ->
[
test_erlang_sleep_available,
test_erlang_sleep_basic,
test_erlang_sleep_zero,
test_erlang_sleep_accuracy,
test_erlang_asyncio_module,
test_erlang_asyncio_gather,
test_erlang_asyncio_wait_for,
test_erlang_asyncio_create_task
].
init_per_suite(Config) ->
{ok, _} = application:ensure_all_started(erlang_python),
timer:sleep(500),
Config.
end_per_suite(_Config) ->
ok.
%% Test that _erlang_sleep is available in py_event_loop
test_erlang_sleep_available(_Config) ->
ok = py:exec(<<"
import py_event_loop as pel
result = hasattr(pel, '_erlang_sleep')
assert result, '_erlang_sleep not found in py_event_loop'
">>),
ct:pal("_erlang_sleep is available"),
ok.
%% Test basic sleep functionality
test_erlang_sleep_basic(_Config) ->
ok = py:exec(<<"
import py_event_loop as pel
# Test basic sleep - should not raise
pel._erlang_sleep(10) # 10ms
">>),
ct:pal("Basic sleep completed"),
ok.
%% Test zero/negative delay returns immediately
test_erlang_sleep_zero(_Config) ->
ok = py:exec(<<"
import py_event_loop as pel
import time
start = time.time()
pel._erlang_sleep(0)
elapsed = (time.time() - start) * 1000
# Should return immediately (< 5ms accounting for Python overhead)
assert elapsed < 5, f'Zero sleep was slow: {elapsed}ms'
">>),
ct:pal("Zero sleep returned fast"),
ok.
%% Test sleep accuracy
test_erlang_sleep_accuracy(_Config) ->
ok = py:exec(<<"
import py_event_loop as pel
import time
delays = [10, 50, 100] # ms
for delay in delays:
start = time.time()
pel._erlang_sleep(delay)
elapsed = (time.time() - start) * 1000
# Allow wide tolerance for CI runners (can be slow/unpredictable)
assert delay * 0.5 <= elapsed <= delay * 10.0, \\
f'{delay}ms sleep took {elapsed:.1f}ms'
">>),
ct:pal("Sleep accuracy within tolerance"),
ok.
%% Test erlang_asyncio module
test_erlang_asyncio_module(_Config) ->
ok = py:exec(<<"
import erlang_asyncio
# Test module has expected functions
funcs = ['sleep', 'get_event_loop', 'new_event_loop', 'run', 'gather', 'wait_for', 'create_task']
for f in funcs:
assert hasattr(erlang_asyncio, f), f'erlang_asyncio missing {f}'
# Test run() with sleep
async def test_sleep():
await erlang_asyncio.sleep(0.01) # 10ms
return 'done'
result = erlang_asyncio.run(test_sleep())
assert result == 'done', f'Expected done, got {result}'
">>),
ct:pal("erlang_asyncio module works"),
ok.
%% Test erlang_asyncio.gather
test_erlang_asyncio_gather(_Config) ->
ok = py:exec(<<"
import erlang_asyncio
async def task(n):
await erlang_asyncio.sleep(0.01)
return n * 2
async def main():
results = await erlang_asyncio.gather(task(1), task(2), task(3))
assert results == [2, 4, 6], f'Expected [2, 4, 6], got {results}'
erlang_asyncio.run(main())
">>),
ct:pal("erlang_asyncio.gather works"),
ok.
%% Test erlang_asyncio.wait_for with timeout
test_erlang_asyncio_wait_for(_Config) ->
ok = py:exec(<<"
import erlang_asyncio
async def fast_task():
await erlang_asyncio.sleep(0.01)
return 'fast'
async def main():
# Should complete before timeout
result = await erlang_asyncio.wait_for(fast_task(), timeout=1.0)
assert result == 'fast', f'Expected fast, got {result}'
erlang_asyncio.run(main())
">>),
ct:pal("erlang_asyncio.wait_for works"),
ok.
%% Test erlang_asyncio.create_task
test_erlang_asyncio_create_task(_Config) ->
ok = py:exec(<<"
import erlang_asyncio
async def background():
await erlang_asyncio.sleep(0.01)
return 'background_done'
async def main():
task = erlang_asyncio.create_task(background())
# Do some other work
await erlang_asyncio.sleep(0.005)
# Wait for task
result = await task
assert result == 'background_done', f'Expected background_done, got {result}'
erlang_asyncio.run(main())
">>),
ct:pal("erlang_asyncio.create_task works"),
ok.