From 022e40cc71beda874d0bad2cec227e472d5dd4af Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Fri, 18 Apr 2025 10:26:19 +0200 Subject: New feature: Linda periodical cancellation checks * lanes.linda() api change: takes all settings in a single table argument * new linda creation argument wake_period * new lanes.configure setting linda_wake_period * adjusted all unit tests (one TODO test fails on purpose) --- unit_tests/embedded_tests.cpp | 4 +- unit_tests/init_and_shutdown.cpp | 533 ++++++++++++--------- unit_tests/linda_tests.cpp | 185 ++++--- unit_tests/scripts/lane/tasking_cancelling.lua | 2 +- .../scripts/lane/tasking_comms_criss_cross.lua | 2 +- unit_tests/scripts/lane/tasking_communications.lua | 2 +- .../scripts/lane/tasking_send_receive_code.lua | 2 +- unit_tests/scripts/linda/multiple_keepers.lua | 6 +- .../scripts/linda/send_registered_userdata.lua | 2 +- 9 files changed, 437 insertions(+), 301 deletions(-) (limited to 'unit_tests') diff --git a/unit_tests/embedded_tests.cpp b/unit_tests/embedded_tests.cpp index 0991a4c..a0a7bb2 100644 --- a/unit_tests/embedded_tests.cpp +++ b/unit_tests/embedded_tests.cpp @@ -157,7 +157,7 @@ TEST_CASE("lanes.embedding.with default allocator") // function with an upvalue std::string_view const _script{ " local lanes = require 'lanes'.configure{with_timers = false}" - " local l = lanes.linda'gleh'" + " local l = lanes.linda{name = 'gleh'}" " local upvalue = 'oeauaoeuoeuaoeuaoeujaoefubycfjbycfybcfjybcfjybcfjbcf'" " local upvalued = function()" " return upvalue" @@ -183,7 +183,7 @@ TEST_CASE("lanes.embedding.with default allocator") // try to send io.open into a linda, which fails if io base library is not loaded std::string_view const _script{ " local lanes = require 'lanes'" - " local l = lanes.linda'gleh'" + " local l = lanes.linda{name = 'gleh'}" " l:set('yo', io.open)" " return 'SUCCESS'" }; diff --git a/unit_tests/init_and_shutdown.cpp b/unit_tests/init_and_shutdown.cpp index 384af43..bd72157 100644 --- a/unit_tests/init_and_shutdown.cpp +++ b/unit_tests/init_and_shutdown.cpp @@ -289,6 +289,62 @@ TEST_CASE("lanes.configure.keepers_gc_threshold") // ################################################################################################# +TEST_CASE("lanes.configure.linda_wake_period") +{ + LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; + + // linda_wake_period should be a number > 0, or 'never' + + SECTION("linda_wake_period = ") + { + L.requireFailure("require 'lanes'.configure{linda_wake_period = {}}"); + } + + // --------------------------------------------------------------------------------------------- + + SECTION("linda_wake_period = ") + { + L.requireFailure("require 'lanes'.configure{linda_wake_period = 'gluh'}"); + } + + // --------------------------------------------------------------------------------------------- + + SECTION("linda_wake_period = 'never'") + { + L.requireSuccess("require 'lanes'.configure{linda_wake_period = 'never'}"); + } + + // --------------------------------------------------------------------------------------------- + + SECTION("linda_wake_period = ") + { + L.requireFailure("require 'lanes'.configure{linda_wake_period = -0.001}"); + } + + // --------------------------------------------------------------------------------------------- + + SECTION("linda_wake_period = 0") + { + L.requireFailure("require 'lanes'.configure{linda_wake_period = 0}"); + } + + // --------------------------------------------------------------------------------------------- + + SECTION("linda_wake_period = 0.0001s") + { + L.requireSuccess("require 'lanes'.configure{linda_wake_period = 0.0001}"); + } + + // --------------------------------------------------------------------------------------------- + + SECTION("linda_wake_period = 1e30") + { + L.requireSuccess("require 'lanes'.configure{linda_wake_period = 1e30}"); + } +} + +// ################################################################################################# + TEST_CASE("lanes.configure.nb_user_keepers") { LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; @@ -300,35 +356,35 @@ TEST_CASE("lanes.configure.nb_user_keepers") L.requireFailure("require 'lanes'.configure{nb_user_keepers = {}}"); } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- SECTION("nb_user_keepers = ") { L.requireFailure("require 'lanes'.configure{nb_user_keepers = 'gluh'}"); } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- SECTION("nb_user_keepers = -1") { L.requireFailure("require 'lanes'.configure{nb_user_keepers = -1}"); } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- SECTION("nb_user_keepers = 0") { L.requireSuccess("require 'lanes'.configure{nb_user_keepers = 0}"); } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- SECTION("nb_user_keepers = 1") { L.requireSuccess("require 'lanes'.configure{nb_user_keepers = 1}"); } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- SECTION("nb_user_keepers = 100") { @@ -345,340 +401,355 @@ TEST_CASE("lanes.configure.nb_user_keepers") // ################################################################################################# -TEST_CASE("lanes.configure.the rest") +TEST_CASE("lanes.configure.on_state_create") { LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; // on_state_create should be a function, either C or Lua, without upvalues - SECTION("on_state_create") + SECTION("on_state_create =
") { - SECTION("on_state_create =
") - { - L.requireFailure("require 'lanes'.configure{on_state_create = {}}"); - } + L.requireFailure("require 'lanes'.configure{on_state_create = {}}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("on_state_create = ") - { - L.requireFailure("require 'lanes'.configure{on_state_create = 'gluh'}"); - } + SECTION("on_state_create = ") + { + L.requireFailure("require 'lanes'.configure{on_state_create = 'gluh'}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("on_state_create = ") - { - L.requireFailure("require 'lanes'.configure{on_state_create = 1}"); - } + SECTION("on_state_create = ") + { + L.requireFailure("require 'lanes'.configure{on_state_create = 1}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("on_state_create = false") - { - L.requireFailure("require 'lanes'.configure{on_state_create = false}"); - } + SECTION("on_state_create = false") + { + L.requireFailure("require 'lanes'.configure{on_state_create = false}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("on_state_create = true") - { - L.requireFailure("require 'lanes'.configure{on_state_create = true}"); - } + SECTION("on_state_create = true") + { + L.requireFailure("require 'lanes'.configure{on_state_create = true}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("on_state_create = ") - { - // on_state_create isn't called inside a Keeper state if it's a Lua function (which is good as print() doesn't exist there!) - L.requireSuccess("local print = print; require 'lanes'.configure{on_state_create = function() print 'hello' end}"); - } + SECTION("on_state_create = ") + { + // on_state_create isn't called inside a Keeper state if it's a Lua function (which is good as print() doesn't exist there!) + L.requireSuccess("local print = print; require 'lanes'.configure{on_state_create = function() print 'hello' end}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("on_state_create = ") - { - // funnily enough, in Lua 5.3, print() uses global tostring(), that doesn't exist in a keeper since we didn't open libs -> "attempt to call a nil value" - // conclusion, don't use print() as a fake on_state_create() callback! - // assert() should be fine since we pass a non-false argument to on_state_create - L.requireSuccess("require 'lanes'.configure{on_state_create = assert}"); - } + SECTION("on_state_create = ") + { + // funnily enough, in Lua 5.3, print() uses global tostring(), that doesn't exist in a keeper since we didn't open libs -> "attempt to call a nil value" + // conclusion, don't use print() as a fake on_state_create() callback! + // assert() should be fine since we pass a non-false argument to on_state_create + L.requireSuccess("require 'lanes'.configure{on_state_create = assert}"); } +} + +// ################################################################################################# + +TEST_CASE("lanes.configure.shutdown_timeout") +{ + LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; - // --------------------------------------------------------------------------------------------- // shutdown_timeout should be a number in [0,3600] - SECTION("shutdown_timeout") + SECTION("shutdown_timeout =
") { - SECTION("shutdown_timeout =
") - { - L.requireFailure("require 'lanes'.configure{shutdown_timeout = {}}"); - } + L.requireFailure("require 'lanes'.configure{shutdown_timeout = {}}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("shutdown_timeout = ") - { - L.requireFailure("require 'lanes'.configure{shutdown_timeout = 'gluh'}"); - } + SECTION("shutdown_timeout = ") + { + L.requireFailure("require 'lanes'.configure{shutdown_timeout = 'gluh'}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("shutdown_timeout = ") - { - L.requireFailure("require 'lanes'.configure{shutdown_timeout = -0.001}"); - } + SECTION("shutdown_timeout = ") + { + L.requireFailure("require 'lanes'.configure{shutdown_timeout = -0.001}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("shutdown_timeout = 0") - { - L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 0}"); - } + SECTION("shutdown_timeout = 0") + { + L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 0}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("shutdown_timeout = 1s") - { - L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 1}"); - } + SECTION("shutdown_timeout = 1s") + { + L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 1}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("shutdown_timeout = 3600s") - { - L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 3600}"); - } + SECTION("shutdown_timeout = 3600s") + { + L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 3600}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("shutdown_timeout = ") - { - L.requireFailure("require 'lanes'.configure{shutdown_timeout = 3600.001}"); - } + SECTION("shutdown_timeout = ") + { + L.requireFailure("require 'lanes'.configure{shutdown_timeout = 3600.001}"); } +} + +// ################################################################################################# + +TEST_CASE("lanes.configure.strip_functions") +{ + LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; - // --------------------------------------------------------------------------------------------- // strip_functions should be a boolean - SECTION("strip_functions") + SECTION("strip_functions =
") { - SECTION("strip_functions =
") - { - L.requireFailure("require 'lanes'.configure{strip_functions = {}}"); - } + L.requireFailure("require 'lanes'.configure{strip_functions = {}}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("strip_functions = ") - { - L.requireFailure("require 'lanes'.configure{strip_functions = 'gluh'}"); - } + SECTION("strip_functions = ") + { + L.requireFailure("require 'lanes'.configure{strip_functions = 'gluh'}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("strip_functions = ") - { - L.requireFailure("require 'lanes'.configure{strip_functions = 1}"); - } + SECTION("strip_functions = ") + { + L.requireFailure("require 'lanes'.configure{strip_functions = 1}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("strip_functions = ") - { - L.requireFailure("require 'lanes'.configure{strip_functions = print}"); - } + SECTION("strip_functions = ") + { + L.requireFailure("require 'lanes'.configure{strip_functions = print}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("strip_functions = false") - { - L.requireSuccess("require 'lanes'.configure{strip_functions = false}"); - } + SECTION("strip_functions = false") + { + L.requireSuccess("require 'lanes'.configure{strip_functions = false}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("strip_functions = true") - { - L.requireSuccess("require 'lanes'.configure{strip_functions = true}"); - } + SECTION("strip_functions = true") + { + L.requireSuccess("require 'lanes'.configure{strip_functions = true}"); } +} + +// ################################################################################################# + +TEST_CASE("lanes.configure.track_lanes") +{ + LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; - // --------------------------------------------------------------------------------------------- // track_lanes should be a boolean - SECTION("track_lanes") + SECTION("track_lanes =
") { - SECTION("track_lanes =
") - { - L.requireFailure("require 'lanes'.configure{track_lanes = {}}"); - } + L.requireFailure("require 'lanes'.configure{track_lanes = {}}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("track_lanes = ") - { - L.requireFailure("require 'lanes'.configure{track_lanes = 'gluh'}"); - } + SECTION("track_lanes = ") + { + L.requireFailure("require 'lanes'.configure{track_lanes = 'gluh'}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("track_lanes = ") - { - L.requireFailure("require 'lanes'.configure{track_lanes = 1}"); - } + SECTION("track_lanes = ") + { + L.requireFailure("require 'lanes'.configure{track_lanes = 1}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("track_lanes = ") - { - L.requireFailure("require 'lanes'.configure{track_lanes = print}"); - } + SECTION("track_lanes = ") + { + L.requireFailure("require 'lanes'.configure{track_lanes = print}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("track_lanes = false") - { - L.requireSuccess("require 'lanes'.configure{track_lanes = false}"); - } + SECTION("track_lanes = false") + { + L.requireSuccess("require 'lanes'.configure{track_lanes = false}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("track_lanes = true") - { - L.requireSuccess("require 'lanes'.configure{track_lanes = true}"); - } + SECTION("track_lanes = true") + { + L.requireSuccess("require 'lanes'.configure{track_lanes = true}"); } +} + +// ################################################################################################# + +TEST_CASE("lanes.configure.verbose_errors") +{ + LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; - // --------------------------------------------------------------------------------------------- // verbose_errors should be a boolean - SECTION("verbose_errors") + SECTION("verbose_errors =
") { - SECTION("verbose_errors =
") - { - L.requireFailure("require 'lanes'.configure{verbose_errors = {}}"); - } + L.requireFailure("require 'lanes'.configure{verbose_errors = {}}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("verbose_errors = ") - { - L.requireFailure("require 'lanes'.configure{verbose_errors = 'gluh'}"); - } + SECTION("verbose_errors = ") + { + L.requireFailure("require 'lanes'.configure{verbose_errors = 'gluh'}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("verbose_errors = ") - { - L.requireFailure("require 'lanes'.configure{verbose_errors = 1}"); - } + SECTION("verbose_errors = ") + { + L.requireFailure("require 'lanes'.configure{verbose_errors = 1}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("verbose_errors = ") - { - L.requireFailure("require 'lanes'.configure{verbose_errors = print}"); - } + SECTION("verbose_errors = ") + { + L.requireFailure("require 'lanes'.configure{verbose_errors = print}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("verbose_errors = false") - { - L.requireSuccess("require 'lanes'.configure{verbose_errors = false}"); - } + SECTION("verbose_errors = false") + { + L.requireSuccess("require 'lanes'.configure{verbose_errors = false}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("verbose_errors = true") - { - L.requireSuccess("require 'lanes'.configure{verbose_errors = true}"); - } + SECTION("verbose_errors = true") + { + L.requireSuccess("require 'lanes'.configure{verbose_errors = true}"); } +} + +// ################################################################################################# + +TEST_CASE("lanes.configure.with_timers") +{ + LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; - // --------------------------------------------------------------------------------------------- // with_timers should be a boolean - SECTION("with_timers") + SECTION("with_timers =
") { - SECTION("with_timers =
") - { - L.requireFailure("require 'lanes'.configure{with_timers = {}}"); - } + L.requireFailure("require 'lanes'.configure{with_timers = {}}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("with_timers = ") - { - L.requireFailure("require 'lanes'.configure{with_timers = 'gluh'}"); - } + SECTION("with_timers = ") + { + L.requireFailure("require 'lanes'.configure{with_timers = 'gluh'}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("with_timers = ") - { - L.requireFailure("require 'lanes'.configure{with_timers = 1}"); - } + SECTION("with_timers = ") + { + L.requireFailure("require 'lanes'.configure{with_timers = 1}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("with_timers = ") - { - L.requireFailure("require 'lanes'.configure{with_timers = print}"); - } + SECTION("with_timers = ") + { + L.requireFailure("require 'lanes'.configure{with_timers = print}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("with_timers = false") - { - L.requireSuccess("require 'lanes'.configure{with_timers = false}"); - } + SECTION("with_timers = false") + { + L.requireSuccess("require 'lanes'.configure{with_timers = false}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("with_timers = true") - { - L.requireSuccess("require 'lanes'.configure{with_timers = true}"); - } + SECTION("with_timers = true") + { + L.requireSuccess("require 'lanes'.configure{with_timers = true}"); } +} + +// ################################################################################################# + +TEST_CASE("lanes.configure.unknown_setting") +{ + LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; - // --------------------------------------------------------------------------------------------- // any unknown setting should be rejected - SECTION("unknown_setting") + SECTION("table setting") { - SECTION("table setting") - { - L.requireFailure("require 'lanes'.configure{[{}] = {}}"); - } + L.requireFailure("require 'lanes'.configure{[{}] = {}}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("boolean setting") - { - L.requireFailure("require 'lanes'.configure{[true] = 'gluh'}"); - } + SECTION("boolean setting") + { + L.requireFailure("require 'lanes'.configure{[true] = 'gluh'}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("function setting") - { - L.requireFailure("require 'lanes'.configure{[function() end] = 1}"); - } + SECTION("function setting") + { + L.requireFailure("require 'lanes'.configure{[function() end] = 1}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("number setting") - { - L.requireFailure("require 'lanes'.configure{[1] = function() end}"); - } + SECTION("number setting") + { + L.requireFailure("require 'lanes'.configure{[1] = function() end}"); + } - // ----------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- - SECTION("unknown string setting") - { - L.requireFailure("require 'lanes'.configure{['gluh'] = false}"); - } + SECTION("unknown string setting") + { + L.requireFailure("require 'lanes'.configure{['gluh'] = false}"); } } diff --git a/unit_tests/linda_tests.cpp b/unit_tests/linda_tests.cpp index f2934eb..9dbaa85 100644 --- a/unit_tests/linda_tests.cpp +++ b/unit_tests/linda_tests.cpp @@ -3,67 +3,132 @@ // ################################################################################################# -TEST_CASE("linda.single Keeper") +TEST_CASE("linda.single_keeper.creation/no_argument") { LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; S.requireSuccess("lanes = require 'lanes'"); - SECTION("Linda creation") - { - // no parameters is ok - S.requireSuccess("lanes.linda()"); - S.requireNotReturnedString("return tostring(lanes.linda())", R"===(Linda: )==="); // unspecified name should not result in - - // since we have only one keeper, only group 0 is authorized - S.requireFailure("lanes.linda(-1)"); - S.requireSuccess("lanes.linda(0)"); - S.requireFailure("lanes.linda(1)"); - - // any name is ok - S.requireSuccess("lanes.linda('')"); // an empty name results in a string conversion of the form "Linda: " that we can't test (but it works) - S.requireReturnedString("return tostring(lanes.linda('short name'))", R"===(Linda: short name)==="); - S.requireReturnedString("return tostring(lanes.linda('very very very very very very long name'))", R"===(Linda: very very very very very very long name)==="); - S.requireReturnedString("return tostring(lanes.linda('auto'))", R"===(Linda: [string "return tostring(lanes.linda('auto'))"]:1)==="); - - if constexpr (LUA_VERSION_NUM == 504) { - // a function is acceptable as a __close handler - S.requireSuccess("local l = lanes.linda(function() end)"); - // a callable table too (a callable full userdata as well, but I have none here) - S.requireSuccess("local l = lanes.linda(setmetatable({}, {__call = function() end}))"); - // if the function raises an error, we should get it - S.requireFailure("local l = lanes.linda(function() error 'gluh' end)"); - } else { - // no __close support before Lua 5.4 - S.requireFailure("lanes.linda(function() end)"); - S.requireFailure("lanes.linda(setmetatable({}, {__call = function() end}))"); - } + // no argument is ok + S.requireSuccess("lanes.linda()"); + S.requireNotReturnedString("return tostring(lanes.linda())", R"===(Linda: )==="); // unspecified name should not result in +} - // mixing parameters in any order is ok: 2 out of 3 - S.requireSuccess("lanes.linda(0, 'name')"); - S.requireSuccess("lanes.linda('name', 0)"); - if constexpr (LUA_VERSION_NUM == 504) { - S.requireSuccess("lanes.linda(0, function() end)"); - S.requireSuccess("lanes.linda(function() end, 0)"); - S.requireSuccess("lanes.linda('name', function() end)"); - S.requireSuccess("lanes.linda(function() end, 'name')"); - } +// ################################################################################################# - // mixing parameters in any order is ok: 3 out of 3 - if constexpr (LUA_VERSION_NUM == 504) { - S.requireSuccess("lanes.linda(0, 'name', function() end)"); - S.requireSuccess("lanes.linda(0, function() end, 'name')"); - S.requireSuccess("lanes.linda('name', 0, function() end)"); - S.requireSuccess("lanes.linda('name', function() end, 0)"); - S.requireSuccess("lanes.linda(function() end, 0, 'name')"); - S.requireSuccess("lanes.linda(function() end, 'name', 0)"); - } +TEST_CASE("linda.single_keeper.creation/non_table_arguments") +{ + LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; + S.requireSuccess("lanes = require 'lanes'"); + + // any argument that is not a table is not ok + S.requireFailure("lanes.linda(0)"); + S.requireFailure("lanes.linda('bob')"); + S.requireFailure("lanes.linda(false)"); + S.requireFailure("lanes.linda(function() end)"); + S.requireFailure("lanes.linda(lanes.cancel_error)"); +} + +// ################################################################################################# + +TEST_CASE("linda.single_keeper.creation/close_handler") +{ + LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; + S.requireSuccess("lanes = require 'lanes'"); + + if constexpr (LUA_VERSION_NUM == 504) { + // a function is acceptable as a __close handler + S.requireSuccess("local l = lanes.linda{close_handler = function() end}"); + // a callable table too (a callable full userdata as well, but I have none here) + S.requireSuccess("local l = lanes.linda{close_handler = setmetatable({}, {__call = function() end})}"); + } else { + // no __close support before Lua 5.4, field is ignored (therefore invalid values are accepted too!) + S.requireSuccess("lanes.linda{close_handler = 'a string'}"); + S.requireSuccess("lanes.linda{close_handler = function() end}"); + S.requireSuccess("lanes.linda{close_handler = setmetatable({}, {__call = function() end})}"); + } +} + +// ################################################################################################# + +TEST_CASE("linda.single_keeper.creation/table_argument") +{ + LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; + S.requireSuccess("lanes = require 'lanes'"); + + // one table is fine + S.requireSuccess("lanes.linda{}"); + // anything beyond that is not + S.requireFailure("lanes.linda({},{})"); + S.requireFailure("lanes.linda({},'bob')"); + S.requireFailure("lanes.linda({},42)"); +} + +// ################################################################################################# + +TEST_CASE("linda.single_keeper.creation/group") +{ + LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; + S.requireSuccess("lanes = require 'lanes'"); + + // since we have only one keeper, only group 0 is authorized + S.requireFailure("lanes.linda{group = -1}"); + S.requireSuccess("lanes.linda{group = 0}"); + S.requireFailure("lanes.linda{group = 1}"); +} + +// ################################################################################################# + +TEST_CASE("linda.single_keeper.creation/name") +{ + LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; + S.requireSuccess("lanes = require 'lanes'"); + + // any name is ok + S.requireSuccess("lanes.linda{name = ''}"); // an empty name results in a string conversion of the form "Linda: " that we can't test (but it works) + S.requireReturnedString("return tostring(lanes.linda{name = 'short name'})", R"===(Linda: short name)==="); + S.requireReturnedString("return tostring(lanes.linda{name = 'very very very very very very long name'})", R"===(Linda: very very very very very very long name)==="); + S.requireReturnedString("return tostring(lanes.linda{name = 'auto'})", R"===(Linda: [string "return tostring(lanes.linda{name = 'auto'})"]:1)==="); +} + +// ################################################################################################# + +TEST_CASE("linda.single_keeper.creation/wake_period") +{ + LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; + S.requireSuccess("lanes = require 'lanes'"); - // unsupported parameters should fail - S.requireFailure("lanes.linda(true)"); - S.requireFailure("lanes.linda(false)"); - // uncallable table or full userdata - S.requireFailure("lanes.linda({})"); - S.requireFailure("lanes.linda(lanes.linda())"); + // wake_period should be a number > 0 + S.requireFailure("lanes.linda{wake_period = false}"); + S.requireFailure("lanes.linda{wake_period = 'bob'}"); + S.requireFailure("lanes.linda{wake_period = {}}"); + S.requireFailure("lanes.linda{wake_period = -1}"); + S.requireFailure("lanes.linda{wake_period = 0}"); + S.requireSuccess("lanes.linda{wake_period = 0.0001}"); +} + +// ################################################################################################# + +TEST_CASE("linda.single_keeper.wake_period") +{ + FAIL("TODO: check that wake_period works as expected"); + // - use configure default if not provided + // - overrides default when provided + // - blocking operation wakes at the specified period +} + +// ################################################################################################# + +TEST_CASE("linda.single_keeper.the_rest") +{ + LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; + S.requireSuccess("lanes = require 'lanes'"); + + // --------------------------------------------------------------------------------------------- + + SECTION("error in close handler is propagated") + { + // if the function raises an error, we should get it + S.requireFailure("local l = lanes.linda{close_handler = function() error 'gluh' end}"); } // --------------------------------------------------------------------------------------------- @@ -311,12 +376,12 @@ TEST_CASE("linda.multi Keeper") S.requireSuccess("lanes = require 'lanes'.configure{nb_user_keepers = 3}"); - S.requireFailure("lanes.linda(-1)"); - S.requireSuccess("lanes.linda(0)"); - S.requireSuccess("lanes.linda(1)"); - S.requireSuccess("lanes.linda(2)"); - S.requireSuccess("lanes.linda(3)"); - S.requireFailure("lanes.linda(4)"); + S.requireFailure("lanes.linda{group = -1}"); + S.requireSuccess("lanes.linda{group = 0}"); + S.requireSuccess("lanes.linda{group = 1}"); + S.requireSuccess("lanes.linda{group = 2}"); + S.requireSuccess("lanes.linda{group = 3}"); + S.requireFailure("lanes.linda{group = 4}"); } // ################################################################################################# diff --git a/unit_tests/scripts/lane/tasking_cancelling.lua b/unit_tests/scripts/lane/tasking_cancelling.lua index ea4516e..873140e 100644 --- a/unit_tests/scripts/lane/tasking_cancelling.lua +++ b/unit_tests/scripts/lane/tasking_cancelling.lua @@ -16,7 +16,7 @@ local lanes_linda = assert(lanes.linda) -- ################################################################################################## -- cancellation of lanes waiting on a linda -local limited = lanes_linda("limited") +local limited = lanes_linda{name = "limited"} assert.fails(function() limited:limit("key", -1) end) assert.failsnot(function() limited:limit("key", 1) end) -- [[################################################ diff --git a/unit_tests/scripts/lane/tasking_comms_criss_cross.lua b/unit_tests/scripts/lane/tasking_comms_criss_cross.lua index 497e81d..610da8b 100644 --- a/unit_tests/scripts/lane/tasking_comms_criss_cross.lua +++ b/unit_tests/scripts/lane/tasking_comms_criss_cross.lua @@ -42,7 +42,7 @@ local tc = lanes_gen("io", { name = 'auto', gc_cb = gc_cb }, end ) -local linda= lanes_linda("criss cross") +local linda= lanes_linda{name = "criss cross"} local a,b= tc(linda, "A","B"), tc(linda, "B","A") -- launching two lanes, twisted comms diff --git a/unit_tests/scripts/lane/tasking_communications.lua b/unit_tests/scripts/lane/tasking_communications.lua index 631d105..01842b4 100644 --- a/unit_tests/scripts/lane/tasking_communications.lua +++ b/unit_tests/scripts/lane/tasking_communications.lua @@ -72,7 +72,7 @@ local chunk= function(linda) WR("chunk ", "Lane ends!\n") end -local linda = lanes_linda("communications") +local linda = lanes_linda{name = "communications"} assert(type(linda) == "userdata" and tostring(linda) == "Linda: communications") -- -- ["->"] master -> slave diff --git a/unit_tests/scripts/lane/tasking_send_receive_code.lua b/unit_tests/scripts/lane/tasking_send_receive_code.lua index e329a88..cb3663f 100644 --- a/unit_tests/scripts/lane/tasking_send_receive_code.lua +++ b/unit_tests/scripts/lane/tasking_send_receive_code.lua @@ -65,7 +65,7 @@ local function chunk2(linda) linda:send("up", function() return ":)" end, "ok2") end -local linda = lanes_linda("auto") +local linda = lanes_linda{name = "auto"} local t2= lanes_gen("debug,package,string,io", { name = 'auto', gc_cb = gc_cb }, chunk2)(linda) -- prepare & launch linda:send("down", function(linda) linda:send("up", "ready!") end, "ok") diff --git a/unit_tests/scripts/linda/multiple_keepers.lua b/unit_tests/scripts/linda/multiple_keepers.lua index 8733087..267d874 100644 --- a/unit_tests/scripts/linda/multiple_keepers.lua +++ b/unit_tests/scripts/linda/multiple_keepers.lua @@ -2,9 +2,9 @@ local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure{nb_user_keepers = 3, keepers_gc_threshold = 500} local lanes = require_lanes_result_1 -local a = lanes.linda("A", 1) -local b = lanes.linda("B", 2) -local c = lanes.linda("C", 3) +local a = lanes.linda{name = "A", group = 1} +local b = lanes.linda{name = "B", group = 2} +local c = lanes.linda{name = "C", group = 3} -- store each linda in the other 2 do diff --git a/unit_tests/scripts/linda/send_registered_userdata.lua b/unit_tests/scripts/linda/send_registered_userdata.lua index 2c0195a..90c05c9 100644 --- a/unit_tests/scripts/linda/send_registered_userdata.lua +++ b/unit_tests/scripts/linda/send_registered_userdata.lua @@ -1,5 +1,5 @@ local lanes = require 'lanes'.configure{with_timers = false} -local l = lanes.linda'gleh' +local l = lanes.linda{name = 'gleh'} l:set('yo', io.stdin) local n, stdin_out = l:get('yo') assert(n == 1 and stdin_out == io.stdin, tostring(stdin_out) .. " ~= " .. tostring(io.stdin)) -- cgit v1.2.3-55-g6feb