aboutsummaryrefslogtreecommitdiff
path: root/unit_tests/lane_tests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unit_tests/lane_tests.cpp')
-rw-r--r--unit_tests/lane_tests.cpp256
1 files changed, 185 insertions, 71 deletions
diff --git a/unit_tests/lane_tests.cpp b/unit_tests/lane_tests.cpp
index d6ef2e0..b6fb188 100644
--- a/unit_tests/lane_tests.cpp
+++ b/unit_tests/lane_tests.cpp
@@ -1,5 +1,7 @@
1#include "_pch.hpp" 1#include "_pch.hpp"
2
2#include "shared.h" 3#include "shared.h"
4#include "lanes/src/threading.hpp"
3 5
4// ################################################################################################# 6// #################################################################################################
5// ################################################################################################# 7// #################################################################################################
@@ -33,7 +35,77 @@ TEST_CASE("lanes.nameof")
33// ################################################################################################# 35// #################################################################################################
34// ################################################################################################# 36// #################################################################################################
35 37
36TEST_CASE("lanes.sleep.argument validation") 38TEST_CASE("lanes.thread_priority_range")
39{
40 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
41 S.requireSuccess("lanes = require 'lanes'.configure()");
42
43 S.requireSuccess("a, b = lanes.thread_priority_range(); print(a, b)");
44 S.requireSuccess("assert(type(a) == 'number' and type(b) == 'number' and b > a)");
45 S.requireSuccess("c, d = lanes.thread_priority_range('native'); print(c, d)");
46 S.requireSuccess("assert(type(c) == 'number' and type(d) == 'number' and d > c)");
47
48 // can't really test the range of values from pthread as they are platform-dependent
49 if constexpr (THREADAPI == THREADAPI_WINDOWS) {
50 // windows constants THREAD_PRIORITY_IDLE and THREAD_PRIORITY_TIME_CRITICAL
51 S.requireSuccess("assert(c == -15 and d == 15)");
52 }
53}
54
55// #################################################################################################
56// #################################################################################################
57
58TEST_CASE("lanes.set_thread_priority")
59{
60 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
61 S.requireSuccess("lanes = require 'lanes'.configure()");
62
63 SECTION("mapped priorities")
64 {
65 std::string_view const _script{
66 " min_prio, max_prio = lanes.thread_priority_range()"
67 " for prio = min_prio, max_prio do"
68 " lanes.set_thread_priority(prio)"
69 " end"
70 };
71 S.requireSuccess(_script);
72
73 S.requireFailure("lanes.set_thread_priority(min_prio - 1)");
74 S.requireFailure("lanes.set_thread_priority(max_prio + 1)");
75 }
76
77 SECTION("native priorities")
78 {
79 S.requireSuccess("min_prio, max_prio = lanes.thread_priority_range('native')");
80 if constexpr (THREADAPI == THREADAPI_WINDOWS) {
81 // Win32 range is -15 to 15, but only some values are accepted
82 S.requireSuccess("lanes.set_thread_priority(-15, 'native')"); // THREAD_PRIORITY_IDLE
83 S.requireFailure("lanes.set_thread_priority(-3, 'native')");
84 S.requireSuccess("lanes.set_thread_priority(-2, 'native')"); // THREAD_PRIORITY_LOWEST
85 S.requireSuccess("lanes.set_thread_priority(-1, 'native')"); // THREAD_PRIORITY_BELOW_NORMAL
86 S.requireSuccess("lanes.set_thread_priority(0, 'native')"); // THREAD_PRIORITY_NORMAL
87 S.requireSuccess("lanes.set_thread_priority(1, 'native')"); // THREAD_PRIORITY_ABOVE_NORMAL
88 S.requireSuccess("lanes.set_thread_priority(2, 'native')"); // THREAD_PRIORITY_HIGHEST
89 S.requireFailure("lanes.set_thread_priority(3, 'native')");
90 S.requireSuccess("lanes.set_thread_priority(-15, 'native')"); // THREAD_PRIORITY_TIME_CRITICAL
91 } else {
92 // until proven otherwise, the full set of values is supported by pthread
93 std::string_view const _script{
94 " for prio = min_prio, max_prio do"
95 " lanes.set_thread_priority(prio, 'native')"
96 " end"
97 };
98 S.requireSuccess(_script);
99 }
100 S.requireFailure("lanes.set_thread_priority(min_prio - 1)");
101 S.requireFailure("lanes.set_thread_priority(max_prio + 1)");
102 }
103}
104
105// #################################################################################################
106// #################################################################################################
107
108TEST_CASE("lanes.sleep.argument_validation/not_numbers")
37{ 109{
38 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; 110 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
39 S.requireSuccess("lanes = require 'lanes'.configure()"); 111 S.requireSuccess("lanes = require 'lanes'.configure()");
@@ -44,6 +116,14 @@ TEST_CASE("lanes.sleep.argument validation")
44 S.requireFailure("lanes.sleep('a string')"); 116 S.requireFailure("lanes.sleep('a string')");
45 S.requireFailure("lanes.sleep(lanes.null)"); 117 S.requireFailure("lanes.sleep(lanes.null)");
46 S.requireFailure("lanes.sleep(print)"); 118 S.requireFailure("lanes.sleep(print)");
119}
120
121// #################################################################################################
122
123TEST_CASE("lanes.sleep.argument_validation/numbers")
124{
125 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
126 S.requireSuccess("lanes = require 'lanes'.configure()");
47 127
48 // negative durations are not supported 128 // negative durations are not supported
49 S.requireFailure("lanes.sleep(-1)"); 129 S.requireFailure("lanes.sleep(-1)");
@@ -97,88 +177,109 @@ TEST_CASE("lanes.sleep.interactions with timers")
97// ################################################################################################# 177// #################################################################################################
98// ################################################################################################# 178// #################################################################################################
99 179
100TEST_CASE("lanes.gen") 180TEST_CASE("lanes.gen.argument_checks")
101{ 181{
102 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; 182 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
103 S.requireSuccess("lanes = require 'lanes'.configure()"); 183 S.requireSuccess("lanes = require 'lanes'.configure()");
104 184
105 // --------------------------------------------------------------------------------------------- 185 // ---------------------------------------------------------------------------------------------
106 186
107 SECTION("argument checks") 187 // no argument is bad
108 { 188 S.requireFailure("lanes.gen()");
109 // no parameter is bad 189
110 S.requireFailure("lanes.gen()"); 190 // minimal generator needs a function
111 191 S.requireSuccess("lanes.gen(function() end)");
112 // minimal generator needs a function 192
113 S.requireSuccess("lanes.gen(function() end)"); 193 // acceptable arguments for the generator are strings, tables, nil, followed by the function body
114 194 S.requireSuccess("lanes.gen(nil, function() end)");
115 // acceptable parameters for the generator are strings, tables, nil, followed by the function body 195 S.requireSuccess("lanes.gen('', function() end)");
116 S.requireSuccess("lanes.gen(nil, function() end)"); 196 S.requireSuccess("lanes.gen({}, function() end)");
117 S.requireSuccess("lanes.gen('', function() end)"); 197 S.requireSuccess("lanes.gen('', {}, function() end)");
118 S.requireSuccess("lanes.gen({}, function() end)"); 198 S.requireSuccess("lanes.gen({}, '', function() end)");
119 S.requireSuccess("lanes.gen('', {}, function() end)"); 199 S.requireSuccess("lanes.gen('', '', function() end)");
120 S.requireSuccess("lanes.gen({}, '', function() end)"); 200 S.requireSuccess("lanes.gen({}, {}, function() end)");
121 S.requireSuccess("lanes.gen('', '', function() end)"); 201
122 S.requireSuccess("lanes.gen({}, {}, function() end)"); 202 // anything different should fail: booleans, numbers, any userdata
123 203 S.requireFailure("lanes.gen(false, function() end)");
124 // anything different should fail: booleans, numbers, any userdata 204 S.requireFailure("lanes.gen(true, function() end)");
125 S.requireFailure("lanes.gen(false, function() end)"); 205 S.requireFailure("lanes.gen(42, function() end)");
126 S.requireFailure("lanes.gen(true, function() end)"); 206 S.requireFailure("lanes.gen(io.stdin, function() end)");
127 S.requireFailure("lanes.gen(42, function() end)"); 207 S.requireFailure("lanes.gen(lanes.linda(), function() end)");
128 S.requireFailure("lanes.gen(io.stdin, function() end)"); 208 S.requireFailure("lanes.gen(lanes.linda():deep(), function() end)");
129 S.requireFailure("lanes.gen(lanes.linda(), function() end)"); 209
130 S.requireFailure("lanes.gen(lanes.linda():deep(), function() end)"); 210 // even if argument types are correct, the function must come last
131 211 S.requireFailure("lanes.gen(function() end, '')");
132 // even if parameter types are correct, the function must come last 212
133 S.requireFailure("lanes.gen(function() end, '')"); 213 // the strings should only list "known base libraries", in any order, or "*"
134 214 // if the particular Lua flavor we build for doesn't support them, they raise an error unless postfixed by '?'
135 // the strings should only list "known base libraries", in any order, or "*" 215 S.requireSuccess("lanes.gen('base', function() end)");
136 // if the particular Lua flavor we build for doesn't support them, they raise an error unless postfixed by '?' 216
137 S.requireSuccess("lanes.gen('base', function() end)"); 217 // bit, ffi, jit are LuaJIT-specific
138
139 // bit, ffi, jit are LuaJIT-specific
140#if LUAJIT_FLAVOR() == 0 218#if LUAJIT_FLAVOR() == 0
141 S.requireFailure("lanes.gen('bit,ffi,jit', function() end)"); 219 S.requireFailure("lanes.gen('bit,ffi,jit', function() end)");
142 S.requireSuccess("lanes.gen('bit?,ffi?,jit?', function() end)"); 220 S.requireSuccess("lanes.gen('bit?,ffi?,jit?', function() end)");
143#endif // LUAJIT_FLAVOR() 221#endif // LUAJIT_FLAVOR()
144 222
145 // bit32 library existed only in Lua 5.2, there is still a loader that will raise an error in Lua 5.3 223 // bit32 library existed only in Lua 5.2, there is still a loader that will raise an error in Lua 5.3
146#if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 224#if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
147 S.requireSuccess("lanes.gen('bit32', function() end)"); 225 S.requireSuccess("lanes.gen('bit32', function() end)");
148#else // LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 226#else // LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
149 S.requireFailure("lanes.gen('bit32', function() end)"); 227 S.requireFailure("lanes.gen('bit32', function() end)");
150 S.requireSuccess("lanes.gen('bit32?', function() end)"); 228 S.requireSuccess("lanes.gen('bit32?', function() end)");
151#endif // LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 229#endif // LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
152 230
153 // coroutine library appeared with Lua 5.2 231 // coroutine library appeared with Lua 5.2
154#if LUA_VERSION_NUM == 501 232#if LUA_VERSION_NUM == 501
155 S.requireFailure("lanes.gen('coroutine', function() end)"); 233 S.requireFailure("lanes.gen('coroutine', function() end)");
156 S.requireSuccess("lanes.gen('coroutine?', function() end)"); 234 S.requireSuccess("lanes.gen('coroutine?', function() end)");
157#endif // LUA_VERSION_NUM == 501 235#endif // LUA_VERSION_NUM == 501
158 236
159 S.requireSuccess("lanes.gen('debug', function() end)"); 237 S.requireSuccess("lanes.gen('debug', function() end)");
160 S.requireSuccess("lanes.gen('io', function() end)"); 238 S.requireSuccess("lanes.gen('io', function() end)");
161 S.requireSuccess("lanes.gen('math', function() end)"); 239 S.requireSuccess("lanes.gen('math', function() end)");
162 S.requireSuccess("lanes.gen('os', function() end)"); 240 S.requireSuccess("lanes.gen('os', function() end)");
163 S.requireSuccess("lanes.gen('package', function() end)"); 241 S.requireSuccess("lanes.gen('package', function() end)");
164 S.requireSuccess("lanes.gen('string', function() end)"); 242 S.requireSuccess("lanes.gen('string', function() end)");
165 S.requireSuccess("lanes.gen('table', function() end)"); 243 S.requireSuccess("lanes.gen('table', function() end)");
166 244
167 // utf8 library appeared with Lua 5.3 245 // utf8 library appeared with Lua 5.3
168#if LUA_VERSION_NUM < 503 246#if LUA_VERSION_NUM < 503
169 S.requireFailure("lanes.gen('utf8', function() end)"); 247 S.requireFailure("lanes.gen('utf8', function() end)");
170 S.requireSuccess("lanes.gen('utf8?', function() end)"); 248 S.requireSuccess("lanes.gen('utf8?', function() end)");
171#endif // LUA_VERSION_NUM < 503 249#endif // LUA_VERSION_NUM < 503
172 250
173 S.requireSuccess("lanes.gen('lanes_core', function() end)"); 251 S.requireSuccess("lanes.gen('lanes_core', function() end)");
174 // "*" repeated or combined with anything else is forbidden 252 // "*" repeated or combined with anything else is forbidden
175 S.requireFailure("lanes.gen('*', '*', function() end)"); 253 S.requireFailure("lanes.gen('*', '*', function() end)");
176 S.requireFailure("lanes.gen('base', '*', function() end)"); 254 S.requireFailure("lanes.gen('base', '*', function() end)");
177 // unknown names are forbidden 255 // unknown names are forbidden
178 S.requireFailure("lanes.gen('Base', function() end)"); 256 S.requireFailure("lanes.gen('Base', function() end)");
179 // repeating the same library more than once is forbidden 257 // repeating the same library more than once is forbidden
180 S.requireFailure("lanes.gen('base,base', function() end)"); 258 S.requireFailure("lanes.gen('base,base', function() end)");
181 } 259}
260
261// #################################################################################################
262// #################################################################################################
263
264TEST_CASE("lanes.gen.priority")
265{
266 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
267 S.requireSuccess("lanes = require 'lanes'.configure()");
268
269 S.requireSuccess("lanes.gen({priority=1}, function() end)");
270 // AFAICT, 1 is accepted by all pthread flavors and win32 API
271 S.requireSuccess("lanes.gen({native_priority=1}, function() end)");
272 // shouldn't be able to provide 2 priority settings
273 S.requireFailure("lanes.gen({priority=1, native_priority=1}, function() end)");
274}
275
276// #################################################################################################
277// #################################################################################################
278
279TEST_CASE("lanes.gen.thread_naming")
280{
281 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
282 S.requireSuccess("lanes = require 'lanes'.configure()");
182 283
183 // --------------------------------------------------------------------------------------------- 284 // ---------------------------------------------------------------------------------------------
184 285
@@ -319,19 +420,24 @@ TEST_CASE("lane.cancel")
319// unfortunately, VS Test adapter does not list individual sections, 420// unfortunately, VS Test adapter does not list individual sections,
320// so let's create a separate test case for each file with an ugly macro... 421// so let's create a separate test case for each file with an ugly macro...
321 422
322#define MAKE_TEST_CASE(DIR, FILE, CONDITION)\ 423#define MAKE_TEST_CASE(DIR, FILE, CONDITION) \
323TEST_CASE("scripted tests." #DIR "." #FILE) \ 424TEST_CASE("scripted_tests." #DIR "." #FILE) \
324{ \ 425{ \
325 FileRunner _runner(R"(.\unit_tests\scripts)"); \ 426 FileRunner _runner(R"(.\unit_tests\scripts)"); \
326 _runner.performTest(FileRunnerParam{ #DIR "/" #FILE, TestType::CONDITION }); \ 427 _runner.performTest(FileRunnerParam{ #DIR "/" #FILE, TestType::CONDITION }); \
327} 428}
328 429
329MAKE_TEST_CASE(lane, cooperative_shutdown, AssertNoLuaError) 430#if LUA_VERSION_NUM >= 504 // this makes use of to-be-closed variables, a Lua 5.4 feature
330#if LUA_VERSION_NUM >= 504 // // warnings are a Lua 5.4 feature 431#define MAKE_TEST_CASE_54(DIR, FILE, CONDITION) MAKE_TEST_CASE(DIR, FILE, CONDITION)
331// NOTE: when this test ends, there are resource leaks and a dangling thread 432#else // LUA_VERSION_NUM
332MAKE_TEST_CASE(lane, uncooperative_shutdown, AssertWarns) 433#define MAKE_TEST_CASE_54(DIR, FILE, CONDITION)
333#endif // LUA_VERSION_NUM 434#endif // LUA_VERSION_NUM
435
436MAKE_TEST_CASE(lane, body_is_a_c_function, AssertNoLuaError)
437MAKE_TEST_CASE(lane, cooperative_shutdown, AssertNoLuaError)
438MAKE_TEST_CASE_54(lane, uncooperative_shutdown, AssertWarns) // NOTE: when this test ends, there are resource leaks and a dangling thread
334MAKE_TEST_CASE(lane, tasking_basic, AssertNoLuaError) 439MAKE_TEST_CASE(lane, tasking_basic, AssertNoLuaError)
440MAKE_TEST_CASE(lane, tasking_cancelling_with_hook, AssertNoLuaError)
335MAKE_TEST_CASE(lane, tasking_cancelling, AssertNoLuaError) 441MAKE_TEST_CASE(lane, tasking_cancelling, AssertNoLuaError)
336MAKE_TEST_CASE(lane, tasking_comms_criss_cross, AssertNoLuaError) 442MAKE_TEST_CASE(lane, tasking_comms_criss_cross, AssertNoLuaError)
337MAKE_TEST_CASE(lane, tasking_communications, AssertNoLuaError) 443MAKE_TEST_CASE(lane, tasking_communications, AssertNoLuaError)
@@ -339,19 +445,27 @@ MAKE_TEST_CASE(lane, tasking_error, AssertNoLuaError)
339MAKE_TEST_CASE(lane, tasking_join_test, AssertNoLuaError) 445MAKE_TEST_CASE(lane, tasking_join_test, AssertNoLuaError)
340MAKE_TEST_CASE(lane, tasking_send_receive_code, AssertNoLuaError) 446MAKE_TEST_CASE(lane, tasking_send_receive_code, AssertNoLuaError)
341MAKE_TEST_CASE(lane, stdlib_naming, AssertNoLuaError) 447MAKE_TEST_CASE(lane, stdlib_naming, AssertNoLuaError)
342MAKE_TEST_CASE(coro, basics, AssertNoLuaError) 448MAKE_TEST_CASE(coro, cancelling_suspended, AssertNoLuaError)
449MAKE_TEST_CASE_54(coro, collect_yielded_lane, AssertNoLuaError)
343#if LUAJIT_FLAVOR() == 0 450#if LUAJIT_FLAVOR() == 0
344// TODO: for some reason, the test fails with LuaJIT. To be investigated 451// TODO: for some reason, the test fails with LuaJIT. To be investigated
345MAKE_TEST_CASE(coro, error_handling, AssertNoLuaError) 452MAKE_TEST_CASE(coro, error_handling, AssertNoLuaError)
346#endif // LUAJIT_FLAVOR() 453#endif // LUAJIT_FLAVOR()
454MAKE_TEST_CASE(coro, index_suspended, AssertNoLuaError)
455MAKE_TEST_CASE(coro, join_suspended, AssertNoLuaError)
456MAKE_TEST_CASE_54(coro, linda_in_close_handler, AssertNoLuaError)
457MAKE_TEST_CASE(coro, regular_function, AssertNoLuaError)
458MAKE_TEST_CASE(coro, resume_basics, AssertNoLuaError)
459MAKE_TEST_CASE(coro, yielding_in_non_coro_errors, AssertNoLuaError)
347 460
348/* 461/*
349TEST_CASE("lanes.scripted tests") 462TEST_CASE("lanes.scripted_tests")
350{ 463{
351 auto const& _testParam = GENERATE( 464 auto const& _testParam = GENERATE(
352 FileRunnerParam{ PUC_LUA_ONLY("lane/cooperative_shutdown"), TestType::AssertNoLuaError }, // 0 465 FileRunnerParam{ PUC_LUA_ONLY("lane/cooperative_shutdown"), TestType::AssertNoLuaError }, // 0
353 FileRunnerParam{ "lane/uncooperative_shutdown", TestType::AssertWarns }, 466 FileRunnerParam{ "lane/uncooperative_shutdown", TestType::AssertWarns },
354 FileRunnerParam{ "lane/tasking_basic", TestType::AssertNoLuaError }, // 2 467 FileRunnerParam{ "lane/tasking_basic", TestType::AssertNoLuaError }, // 2
468 FileRunnerParam{ "lane/tasking_cancelling_with_hook", TestType::AssertNoLuaError }, // 3
355 FileRunnerParam{ "lane/tasking_cancelling", TestType::AssertNoLuaError }, // 3 469 FileRunnerParam{ "lane/tasking_cancelling", TestType::AssertNoLuaError }, // 3
356 FileRunnerParam{ "lane/tasking_comms_criss_cross", TestType::AssertNoLuaError }, // 4 470 FileRunnerParam{ "lane/tasking_comms_criss_cross", TestType::AssertNoLuaError }, // 4
357 FileRunnerParam{ "lane/tasking_communications", TestType::AssertNoLuaError }, 471 FileRunnerParam{ "lane/tasking_communications", TestType::AssertNoLuaError },