aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2025-04-18 17:53:27 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2025-04-18 17:53:27 +0200
commit4c5d11823802175cfaf083a6fcd20a3006b27d51 (patch)
tree95ecb36d71620d5f61f5c06f3f022a3667181606
parent022e40cc71beda874d0bad2cec227e472d5dd4af (diff)
downloadlanes-4c5d11823802175cfaf083a6fcd20a3006b27d51.tar.gz
lanes-4c5d11823802175cfaf083a6fcd20a3006b27d51.tar.bz2
lanes-4c5d11823802175cfaf083a6fcd20a3006b27d51.zip
A unit test for linda wake_period
Diffstat (limited to '')
-rw-r--r--src/linda.cpp10
-rw-r--r--src/macros_and_utils.hpp1
-rw-r--r--tests/track_lanes.lua6
-rw-r--r--unit_tests/UnitTests.vcxproj1
-rw-r--r--unit_tests/UnitTests.vcxproj.filters3
-rw-r--r--unit_tests/linda_tests.cpp17
-rw-r--r--unit_tests/scripts/linda/wake_period.lua41
7 files changed, 64 insertions, 15 deletions
diff --git a/src/linda.cpp b/src/linda.cpp
index a9ae61c..fa28385 100644
--- a/src/linda.cpp
+++ b/src/linda.cpp
@@ -1178,7 +1178,15 @@ LUAG_FUNC(linda)
1178 if (lua_isnil(L_, kIdxTop)) { 1178 if (lua_isnil(L_, kIdxTop)) {
1179 lua_pop(L_, 1); 1179 lua_pop(L_, 1);
1180 lua_pushnumber(L_, _U->lindaWakePeriod.count()); 1180 lua_pushnumber(L_, _U->lindaWakePeriod.count());
1181 } else { 1181 } else if (luaG_type(L_, kIdxTop) == LuaType::STRING) {
1182 if (luaG_tostring(L_, kIdxTop) != "never") {
1183 luaL_argerror(L_, 1, "invalid wake_period");
1184 } else {
1185 lua_pop(L_, 1);
1186 lua_pushnumber(L_, 0);
1187 }
1188 }
1189 else {
1182 luaL_argcheck(L_, luaL_optnumber(L_, 2, 0) > 0, 1, "wake_period must be > 0"); 1190 luaL_argcheck(L_, luaL_optnumber(L_, 2, 0) > 0, 1, "wake_period must be > 0");
1183 } 1191 }
1184 1192
diff --git a/src/macros_and_utils.hpp b/src/macros_and_utils.hpp
index 16011f7..1aca818 100644
--- a/src/macros_and_utils.hpp
+++ b/src/macros_and_utils.hpp
@@ -21,6 +21,7 @@ inline void STACK_GROW(lua_State* const L_, int const n_)
21 21
22// ################################################################################################# 22// #################################################################################################
23 23
24// 1 unit of lua_Duration lasts 1 second (using default period of std::ratio<1>)
24using lua_Duration = std::chrono::template duration<lua_Number>; 25using lua_Duration = std::chrono::template duration<lua_Number>;
25 26
26// ################################################################################################# 27// #################################################################################################
diff --git a/tests/track_lanes.lua b/tests/track_lanes.lua
index d1670ae..ef2ca06 100644
--- a/tests/track_lanes.lua
+++ b/tests/track_lanes.lua
@@ -59,8 +59,10 @@ local threads = track( "============= START", 2)
59-- two_seconds forever 59-- two_seconds forever
60assert(threads[1].status == 'waiting' and threads[2].status == 'waiting') 60assert(threads[1].status == 'waiting' and threads[2].status == 'waiting')
61 61
62-- wait until ephemeral1 has completed 62-- wait until ephemeral1 has completed, should take about 2 seconds
63SLEEP(2.1) 63repeat
64 SLEEP(0.1)
65until ephemeral1.status == "done"
64 66
65local threads = track( "============= two_seconds dead", 2) 67local threads = track( "============= two_seconds dead", 2)
66-- two_seconds forever 68-- two_seconds forever
diff --git a/unit_tests/UnitTests.vcxproj b/unit_tests/UnitTests.vcxproj
index e1370c3..8c22653 100644
--- a/unit_tests/UnitTests.vcxproj
+++ b/unit_tests/UnitTests.vcxproj
@@ -968,6 +968,7 @@
968 <ItemGroup> 968 <ItemGroup>
969 <None Include="..\.runsettings" /> 969 <None Include="..\.runsettings" />
970 <None Include="scripts\lane\tasking_cancelling_with_hook.lua" /> 970 <None Include="scripts\lane\tasking_cancelling_with_hook.lua" />
971 <None Include="scripts\linda\wake_period.lua" />
971 <None Include="UnitTests.makefile" /> 972 <None Include="UnitTests.makefile" />
972 <None Include="scripts\coro\basics.lua" /> 973 <None Include="scripts\coro\basics.lua" />
973 <None Include="scripts\coro\error_handling.lua" /> 974 <None Include="scripts\coro\error_handling.lua" />
diff --git a/unit_tests/UnitTests.vcxproj.filters b/unit_tests/UnitTests.vcxproj.filters
index b0ce216..ce8cb58 100644
--- a/unit_tests/UnitTests.vcxproj.filters
+++ b/unit_tests/UnitTests.vcxproj.filters
@@ -116,5 +116,8 @@
116 <None Include="scripts\lane\tasking_cancelling_with_hook.lua"> 116 <None Include="scripts\lane\tasking_cancelling_with_hook.lua">
117 <Filter>Scripts\lane</Filter> 117 <Filter>Scripts\lane</Filter>
118 </None> 118 </None>
119 <None Include="scripts\linda\wake_period.lua">
120 <Filter>Scripts\linda</Filter>
121 </None>
119 </ItemGroup> 122 </ItemGroup>
120</Project> \ No newline at end of file 123</Project> \ No newline at end of file
diff --git a/unit_tests/linda_tests.cpp b/unit_tests/linda_tests.cpp
index 9dbaa85..d956ae2 100644
--- a/unit_tests/linda_tests.cpp
+++ b/unit_tests/linda_tests.cpp
@@ -104,16 +104,7 @@ TEST_CASE("linda.single_keeper.creation/wake_period")
104 S.requireFailure("lanes.linda{wake_period = -1}"); 104 S.requireFailure("lanes.linda{wake_period = -1}");
105 S.requireFailure("lanes.linda{wake_period = 0}"); 105 S.requireFailure("lanes.linda{wake_period = 0}");
106 S.requireSuccess("lanes.linda{wake_period = 0.0001}"); 106 S.requireSuccess("lanes.linda{wake_period = 0.0001}");
107} 107 S.requireSuccess("lanes.linda{wake_period = 'never'}");
108
109// #################################################################################################
110
111TEST_CASE("linda.single_keeper.wake_period")
112{
113 FAIL("TODO: check that wake_period works as expected");
114 // - use configure default if not provided
115 // - overrides default when provided
116 // - blocking operation wakes at the specified period
117} 108}
118 109
119// ################################################################################################# 110// #################################################################################################
@@ -397,17 +388,19 @@ TEST_CASE("scripted_tests." #DIR "." #FILE) \
397 _runner.performTest(FileRunnerParam{ #DIR "/" #FILE, TestType::AssertNoLuaError }); \ 388 _runner.performTest(FileRunnerParam{ #DIR "/" #FILE, TestType::AssertNoLuaError }); \
398} 389}
399 390
391MAKE_TEST_CASE(linda, multiple_keepers)
400MAKE_TEST_CASE(linda, send_receive) 392MAKE_TEST_CASE(linda, send_receive)
401MAKE_TEST_CASE(linda, send_registered_userdata) 393MAKE_TEST_CASE(linda, send_registered_userdata)
402MAKE_TEST_CASE(linda, multiple_keepers) 394MAKE_TEST_CASE(linda, wake_period)
403 395
404/* 396/*
405TEST_CASE("linda.scripted_tests") 397TEST_CASE("linda.scripted_tests")
406{ 398{
407 auto const& _testParam = GENERATE( 399 auto const& _testParam = GENERATE(
400 FileRunnerParam{ "linda/multiple_keepers", TestType::AssertNoLuaError },
408 FileRunnerParam{ "linda/send_receive", TestType::AssertNoLuaError }, 401 FileRunnerParam{ "linda/send_receive", TestType::AssertNoLuaError },
409 FileRunnerParam{ "linda/send_registered_userdata", TestType::AssertNoLuaError }, 402 FileRunnerParam{ "linda/send_registered_userdata", TestType::AssertNoLuaError },
410 FileRunnerParam{ "linda/multiple_keepers", TestType::AssertNoLuaError } 403 FileRunnerParam{ "linda/wake_period", TestType::AssertNoLuaError }
411 ); 404 );
412 405
413 FileRunner _runner(R"(.\unit_tests\scripts)"); 406 FileRunner _runner(R"(.\unit_tests\scripts)");
diff --git a/unit_tests/scripts/linda/wake_period.lua b/unit_tests/scripts/linda/wake_period.lua
new file mode 100644
index 0000000..e4a900d
--- /dev/null
+++ b/unit_tests/scripts/linda/wake_period.lua
@@ -0,0 +1,41 @@
1-- default wake period is 0.5 seconds
2local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure{linda_wake_period = 0.5}
3local lanes = require_lanes_result_1
4
5-- a lane that performs a blocking operation for 2 seconds
6local body = function(linda_)
7 -- a blocking read that lasts longer than the tested wake_period values
8 linda_:receive(2, "empty_slot")
9 return true
10end
11
12-- if we don't cancel the lane, we should wait the whole duration
13local function check_wake_duration(linda_, expected_, do_cancel_)
14 local h = lanes.gen(body)(linda_)
15 -- wait until the linda is blocked
16 repeat until h.status == "waiting"
17 local t0 = lanes.now_secs()
18 -- soft cancel, no timeout, no waking
19 if do_cancel_ then
20 local result, reason = h:cancel('soft', 0, false)
21 -- should say there was a timeout, since the lane didn't actually cancel (normal since we did not wake it)
22 assert(result == false and reason == 'timeout', "unexpected cancel result")
23 end
24 -- this should wait until the linda wakes by itself before the actual receive timeout and sees the cancel request
25 h:join()
26 local t1 = lanes.now_secs()
27 local delta = t1 - t0
28 -- the linda should check for cancellation at about the expected period, not earlier
29 assert(delta >= expected_, tostring(linda_) .. " woke too early:" .. delta)
30 -- the lane shouldn't terminate too long after cancellation was processed
31 assert(delta <= expected_ * 1.1, tostring(linda_) .. " woke too late: " .. delta)
32end
33
34-- legacy behavior: linda waits until operation timeout
35check_wake_duration(lanes.linda{name = "A", wake_period = 'never'}, 2, true)
36-- early wake behavior: linda wakes after the expected time, sees a cancellation requests, and aborts the operation early
37check_wake_duration(lanes.linda{name = "B", wake_period = 0.25}, 0.25, true)
38check_wake_duration(lanes.linda{name = "C"}, 0.5, true) -- wake_period defaults to 0.5 (see above)
39check_wake_duration(lanes.linda{name = "D", wake_period = 1}, 1, true)
40-- even when there is a wake_period, the operation should reach full timeout if not cancelled early
41check_wake_duration(lanes.linda{name = "E", wake_period = 0.1}, 2, false)