diff options
Diffstat (limited to 'unit_tests/linda_tests.cpp')
-rw-r--r-- | unit_tests/linda_tests.cpp | 333 |
1 files changed, 199 insertions, 134 deletions
diff --git a/unit_tests/linda_tests.cpp b/unit_tests/linda_tests.cpp index efdb8a5..90630a7 100644 --- a/unit_tests/linda_tests.cpp +++ b/unit_tests/linda_tests.cpp | |||
@@ -3,154 +3,216 @@ | |||
3 | 3 | ||
4 | // ################################################################################################# | 4 | // ################################################################################################# |
5 | 5 | ||
6 | TEST_CASE("linda.single Keeper") | 6 | TEST_CASE("linda.single_keeper.creation/no_argument") |
7 | { | 7 | { |
8 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | 8 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; |
9 | S.requireSuccess("lanes = require 'lanes'"); | 9 | S.requireSuccess("lanes = require 'lanes'"); |
10 | 10 | ||
11 | SECTION("Linda creation") | 11 | // no argument is ok |
12 | { | 12 | S.requireSuccess("lanes.linda()"); |
13 | // no parameters is ok | 13 | S.requireNotReturnedString("return tostring(lanes.linda())", R"===(Linda: <not a string>)==="); // unspecified name should not result in <not a string> |
14 | S.requireSuccess("lanes.linda()"); | 14 | } |
15 | S.requireNotReturnedString("return tostring(lanes.linda())", R"===(Linda: <not a string>)==="); // unspecified name should not result in <not a string> | ||
16 | |||
17 | // since we have only one keeper, only group 0 is authorized | ||
18 | S.requireFailure("lanes.linda(-1)"); | ||
19 | S.requireSuccess("lanes.linda(0)"); | ||
20 | S.requireFailure("lanes.linda(1)"); | ||
21 | |||
22 | // any name is ok | ||
23 | S.requireSuccess("lanes.linda('')"); // an empty name results in a string conversion of the form "Linda: <some hex value>" that we can't test (but it works) | ||
24 | S.requireReturnedString("return tostring(lanes.linda('short name'))", R"===(Linda: short name)==="); | ||
25 | S.requireReturnedString("return tostring(lanes.linda('very very very very very very long name'))", R"===(Linda: very very very very very very long name)==="); | ||
26 | S.requireReturnedString("return tostring(lanes.linda('auto'))", R"===(Linda: [string "return tostring(lanes.linda('auto'))"]:1)==="); | ||
27 | |||
28 | if constexpr (LUA_VERSION_NUM == 504) { | ||
29 | // a function is acceptable as a __close handler | ||
30 | S.requireSuccess("local l <close> = lanes.linda(function() end)"); | ||
31 | // a callable table too (a callable full userdata as well, but I have none here) | ||
32 | S.requireSuccess("local l <close> = lanes.linda(setmetatable({}, {__call = function() end}))"); | ||
33 | // if the function raises an error, we should get it | ||
34 | S.requireFailure("local l <close> = lanes.linda(function() error 'gluh' end)"); | ||
35 | } else { | ||
36 | // no __close support before Lua 5.4 | ||
37 | S.requireFailure("lanes.linda(function() end)"); | ||
38 | S.requireFailure("lanes.linda(setmetatable({}, {__call = function() end}))"); | ||
39 | } | ||
40 | 15 | ||
41 | // mixing parameters in any order is ok: 2 out of 3 | 16 | // ################################################################################################# |
42 | S.requireSuccess("lanes.linda(0, 'name')"); | ||
43 | S.requireSuccess("lanes.linda('name', 0)"); | ||
44 | if constexpr (LUA_VERSION_NUM == 504) { | ||
45 | S.requireSuccess("lanes.linda(0, function() end)"); | ||
46 | S.requireSuccess("lanes.linda(function() end, 0)"); | ||
47 | S.requireSuccess("lanes.linda('name', function() end)"); | ||
48 | S.requireSuccess("lanes.linda(function() end, 'name')"); | ||
49 | } | ||
50 | 17 | ||
51 | // mixing parameters in any order is ok: 3 out of 3 | 18 | TEST_CASE("linda.single_keeper.creation/non_table_arguments") |
52 | if constexpr (LUA_VERSION_NUM == 504) { | 19 | { |
53 | S.requireSuccess("lanes.linda(0, 'name', function() end)"); | 20 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; |
54 | S.requireSuccess("lanes.linda(0, function() end, 'name')"); | 21 | S.requireSuccess("lanes = require 'lanes'"); |
55 | S.requireSuccess("lanes.linda('name', 0, function() end)"); | 22 | |
56 | S.requireSuccess("lanes.linda('name', function() end, 0)"); | 23 | // any argument that is not a table is not ok |
57 | S.requireSuccess("lanes.linda(function() end, 0, 'name')"); | 24 | S.requireFailure("lanes.linda(0)"); |
58 | S.requireSuccess("lanes.linda(function() end, 'name', 0)"); | 25 | S.requireFailure("lanes.linda('bob')"); |
59 | } | 26 | S.requireFailure("lanes.linda(false)"); |
27 | S.requireFailure("lanes.linda(function() end)"); | ||
28 | S.requireFailure("lanes.linda(lanes.cancel_error)"); | ||
29 | } | ||
30 | |||
31 | // ################################################################################################# | ||
60 | 32 | ||
61 | // unsupported parameters should fail | 33 | TEST_CASE("linda.single_keeper.creation/close_handler") |
62 | S.requireFailure("lanes.linda(true)"); | 34 | { |
63 | S.requireFailure("lanes.linda(false)"); | 35 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; |
64 | // uncallable table or full userdata | 36 | S.requireSuccess("lanes = require 'lanes'"); |
65 | S.requireFailure("lanes.linda({})"); | 37 | |
66 | S.requireFailure("lanes.linda(lanes.linda())"); | 38 | if constexpr (LUA_VERSION_NUM >= 504) { |
39 | // a function is acceptable as a __close handler | ||
40 | S.requireSuccess("local l <close> = lanes.linda{close_handler = function() end}"); | ||
41 | // a callable table too (a callable full userdata as well, but I have none here) | ||
42 | S.requireSuccess("local l <close> = lanes.linda{close_handler = setmetatable({}, {__call = function() end})}"); | ||
43 | } else { | ||
44 | // no __close support before Lua 5.4, field is ignored (therefore invalid values are accepted too!) | ||
45 | S.requireSuccess("lanes.linda{close_handler = 'a string'}"); | ||
46 | S.requireSuccess("lanes.linda{close_handler = function() end}"); | ||
47 | S.requireSuccess("lanes.linda{close_handler = setmetatable({}, {__call = function() end})}"); | ||
67 | } | 48 | } |
49 | } | ||
68 | 50 | ||
69 | // --------------------------------------------------------------------------------------------- | 51 | // ################################################################################################# |
52 | |||
53 | TEST_CASE("linda.single_keeper.creation/table_argument") | ||
54 | { | ||
55 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | ||
56 | S.requireSuccess("lanes = require 'lanes'"); | ||
57 | |||
58 | // one table is fine | ||
59 | S.requireSuccess("lanes.linda{}"); | ||
60 | // anything beyond that is not | ||
61 | S.requireFailure("lanes.linda({},{})"); | ||
62 | S.requireFailure("lanes.linda({},'bob')"); | ||
63 | S.requireFailure("lanes.linda({},42)"); | ||
64 | } | ||
65 | |||
66 | // ################################################################################################# | ||
67 | |||
68 | TEST_CASE("linda.single_keeper.creation/group") | ||
69 | { | ||
70 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | ||
71 | S.requireSuccess("lanes = require 'lanes'"); | ||
72 | |||
73 | // since we have only one keeper, only group 0 is authorized | ||
74 | S.requireFailure("lanes.linda{group = -1}"); | ||
75 | S.requireSuccess("lanes.linda{group = 0}"); | ||
76 | S.requireFailure("lanes.linda{group = 1}"); | ||
77 | } | ||
78 | |||
79 | // ################################################################################################# | ||
80 | |||
81 | TEST_CASE("linda.single_keeper.creation/name") | ||
82 | { | ||
83 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | ||
84 | S.requireSuccess("lanes = require 'lanes'"); | ||
85 | |||
86 | // any name is ok | ||
87 | S.requireSuccess("lanes.linda{name = ''}"); // an empty name results in a string conversion of the form "Linda: <some hex value>" that we can't test (but it works) | ||
88 | S.requireReturnedString("return tostring(lanes.linda{name = 'short name'})", R"===(Linda: short name)==="); | ||
89 | 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)==="); | ||
90 | S.requireReturnedString("return tostring(lanes.linda{name = 'auto'})", R"===(Linda: [string "return tostring(lanes.linda{name = 'auto'})"]:1)==="); | ||
91 | } | ||
92 | |||
93 | // ################################################################################################# | ||
94 | |||
95 | TEST_CASE("linda.single_keeper.creation/wake_period") | ||
96 | { | ||
97 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | ||
98 | S.requireSuccess("lanes = require 'lanes'"); | ||
99 | |||
100 | // wake_period should be a number > 0 | ||
101 | S.requireFailure("lanes.linda{wake_period = false}"); | ||
102 | S.requireFailure("lanes.linda{wake_period = 'bob'}"); | ||
103 | S.requireFailure("lanes.linda{wake_period = {}}"); | ||
104 | S.requireFailure("lanes.linda{wake_period = -1}"); | ||
105 | S.requireFailure("lanes.linda{wake_period = 0}"); | ||
106 | S.requireSuccess("lanes.linda{wake_period = 0.0001}"); | ||
107 | S.requireSuccess("lanes.linda{wake_period = 'never'}"); | ||
108 | } | ||
109 | |||
110 | // ################################################################################################# | ||
70 | 111 | ||
71 | SECTION("Linda indexing") | 112 | TEST_CASE("linda.single_keeper.indexing") |
113 | { | ||
114 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | ||
115 | S.requireSuccess("lanes = require 'lanes'.configure()"); | ||
116 | |||
117 | // indexing the linda with an unknown string key should fail | ||
118 | S.requireFailure("return lanes.linda().gouikra"); | ||
119 | // indexing the linda with an unsupported key type should fail | ||
120 | S.requireFailure("return lanes.linda()[5]"); | ||
121 | S.requireFailure("return lanes.linda()[false]"); | ||
122 | S.requireFailure("return lanes.linda()[{}]"); | ||
123 | S.requireFailure("return lanes.linda()[function() end]"); | ||
124 | } | ||
125 | |||
126 | // ################################################################################################# | ||
127 | |||
128 | TEST_CASE("linda.single_keeper.send()") | ||
129 | { | ||
130 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | ||
131 | S.requireSuccess("lanes = require 'lanes'.configure()"); | ||
132 | |||
133 | SECTION("timeout") | ||
72 | { | 134 | { |
73 | // indexing the linda with an unknown string key should fail | 135 | // timeout checks |
74 | S.requireFailure("return lanes.linda().gouikra"); | 136 | // linda:send() should fail if the timeout is bad |
75 | // indexing the linda with an unsupported key type should fail | 137 | S.requireFailure("lanes.linda():send(-1, 'k', 'v')"); |
76 | S.requireFailure("return lanes.linda()[5]"); | 138 | // any positive value is ok |
77 | S.requireFailure("return lanes.linda()[false]"); | 139 | S.requireSuccess("lanes.linda():send(0, 'k', 'v')"); |
78 | S.requireFailure("return lanes.linda()[{}]"); | 140 | S.requireSuccess("lanes.linda():send(1e20, 'k', 'v')"); |
79 | S.requireFailure("return lanes.linda()[function() end]"); | 141 | // nil too (same as 'forever') |
142 | S.requireSuccess("lanes.linda():send(nil, 'k', 'v')"); | ||
80 | } | 143 | } |
81 | 144 | ||
82 | // --------------------------------------------------------------------------------------------- | 145 | // ----------------------------------------------------------------------------------------- |
83 | SECTION("linda:send()") | 146 | |
147 | SECTION("fails on bad keys") | ||
84 | { | 148 | { |
85 | SECTION("timeout") | 149 | // key checks |
86 | { | 150 | // linda:send() should fail if the key is unsupported (nil, table, function, full userdata, reserved light userdata) |
87 | // timeout checks | 151 | S.requireFailure("lanes.linda():send(0, nil, 'v')"); |
88 | // linda:send() should fail if the timeout is bad | 152 | S.requireFailure("lanes.linda():send(0, {}, 'v')"); |
89 | S.requireFailure("lanes.linda():send(-1, 'k', 'v')"); | 153 | S.requireFailure("lanes.linda():send(0, function() end, 'v')"); |
90 | // any positive value is ok | 154 | S.requireFailure("lanes.linda():send(0, io.stdin, 'v')"); |
91 | S.requireSuccess("lanes.linda():send(0, 'k', 'v')"); | 155 | S.requireFailure("lanes.linda():send(0, lanes.null, 'v')"); |
92 | S.requireSuccess("lanes.linda():send(1e20, 'k', 'v')"); | 156 | S.requireFailure("lanes.linda():send(0, lanes.cancel_error, 'v')"); |
93 | // nil too (same as 'forever') | 157 | } |
94 | S.requireSuccess("lanes.linda():send(nil, 'k', 'v')"); | ||
95 | } | ||
96 | 158 | ||
97 | // ----------------------------------------------------------------------------------------- | 159 | // ----------------------------------------------------------------------------------------- |
98 | 160 | ||
99 | SECTION("fails on bad keys") | 161 | SECTION("succeeds on supported keys") |
100 | { | 162 | { |
101 | // key checks | 163 | // supported keys are ok: boolean, number, string, light userdata, deep userdata |
102 | // linda:send() should fail if the key is unsupported (nil, table, function, full userdata, reserved light userdata) | 164 | S.requireSuccess("lanes.linda():send(0, true, 'v')"); |
103 | S.requireFailure("lanes.linda():send(0, nil, 'v')"); | 165 | S.requireSuccess("lanes.linda():send(0, false, 'v')"); |
104 | S.requireFailure("lanes.linda():send(0, {}, 'v')"); | 166 | S.requireSuccess("lanes.linda():send(0, 99, 'v')"); |
105 | S.requireFailure("lanes.linda():send(0, function() end, 'v')"); | 167 | S.requireSuccess("local l = lanes.linda(); l:send(0, l:deep(), 'v')"); |
106 | S.requireFailure("lanes.linda():send(0, io.stdin, 'v')"); | 168 | } |
107 | S.requireFailure("lanes.linda():send(0, lanes.null, 'v')"); | ||
108 | S.requireFailure("lanes.linda():send(0, lanes.cancel_error, 'v')"); | ||
109 | S.requireFailure("local l = lanes.linda(); l:send(0, l.batched, 'v')"); | ||
110 | } | ||
111 | 169 | ||
112 | // ----------------------------------------------------------------------------------------- | 170 | // ----------------------------------------------------------------------------------------- |
113 | 171 | ||
114 | SECTION("succeeds on supported keys") | 172 | SECTION("succeeds on deep userdata key") |
115 | { | 173 | { |
116 | // supported keys are ok: boolean, number, string, light userdata, deep userdata | 174 | S.requireSuccess("local l = lanes.linda(); l:send(0, l, 'v')"); |
117 | S.requireSuccess("lanes.linda():send(0, true, 'v')"); | 175 | } |
118 | S.requireSuccess("lanes.linda():send(0, false, 'v')"); | ||
119 | S.requireSuccess("lanes.linda():send(0, 99, 'v')"); | ||
120 | S.requireSuccess("local l = lanes.linda(); l:send(0, l:deep(), 'v')"); | ||
121 | } | ||
122 | 176 | ||
123 | // ----------------------------------------------------------------------------------------- | 177 | // ----------------------------------------------------------------------------------------- |
124 | 178 | ||
125 | SECTION("succeeds on deep userdata key") | 179 | SECTION(". fails") |
126 | { | 180 | { |
127 | S.requireSuccess("local l = lanes.linda(); l:send(0, l, 'v')"); | 181 | // misuse checks, . instead of : |
128 | } | 182 | S.requireFailure("lanes.linda().send(nil, 'k', 'v')"); |
183 | } | ||
129 | 184 | ||
130 | // ----------------------------------------------------------------------------------------- | 185 | // ----------------------------------------------------------------------------------------- |
131 | 186 | ||
132 | SECTION(". fails") | 187 | SECTION("unsupported values fail") |
133 | { | 188 | { |
134 | // misuse checks, . instead of : | 189 | // value checks |
135 | S.requireFailure("lanes.linda().send(nil, 'k', 'v')"); | 190 | // linda:send() should fail if we don't send anything |
136 | } | 191 | S.requireFailure("lanes.linda():send()"); |
192 | S.requireFailure("lanes.linda():send(0)"); | ||
193 | S.requireFailure("lanes.linda():send(0, 'k')"); | ||
194 | // or non-deep userdata | ||
195 | S.requireFailure("lanes.linda():send(0, 'k', fixture.newuserdata())"); | ||
196 | // or something with a converter that raises an error (maybe that should go to a dedicated __lanesconvert test!) | ||
197 | S.requireFailure("lanes.linda():send(0, 'k', setmetatable({}, {__lanesconvert = function(where_) error (where_ .. ': should not send me' end}))"); | ||
198 | // but a registered non-deep userdata should work | ||
199 | S.requireSuccess("lanes.linda():send(0, 'k', io.stdin)"); | ||
200 | } | ||
201 | } | ||
137 | 202 | ||
138 | // ----------------------------------------------------------------------------------------- | 203 | // ################################################################################################# |
139 | 204 | ||
140 | SECTION("unsupported values fail") | 205 | TEST_CASE("linda.single_keeper.the_rest") |
141 | { | 206 | { |
142 | // value checks | 207 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; |
143 | // linda:send() should fail if we don't send anything | 208 | S.requireSuccess("lanes = require 'lanes'"); |
144 | S.requireFailure("lanes.linda():send()"); | 209 | |
145 | S.requireFailure("lanes.linda():send(0)"); | 210 | // --------------------------------------------------------------------------------------------- |
146 | S.requireFailure("lanes.linda():send(0, 'k')"); | 211 | |
147 | // or non-deep userdata | 212 | SECTION("error in close handler is propagated") |
148 | S.requireFailure("lanes.linda():send(0, 'k', fixture.newuserdata())"); | 213 | { |
149 | // or something with a converter that raises an error (maybe that should go to a dedicated __lanesconvert test!) | 214 | // if the function raises an error, we should get it |
150 | S.requireFailure("lanes.linda():send(0, 'k', setmetatable({}, {__lanesconvert = function(where_) error (where_ .. ': should not send me' end}))"); | 215 | S.requireFailure("local l <close> = lanes.linda{close_handler = function() error 'gluh' end}"); |
151 | // but a registered non-deep userdata should work | ||
152 | S.requireSuccess("lanes.linda():send(0, 'k', io.stdin)"); | ||
153 | } | ||
154 | } | 216 | } |
155 | 217 | ||
156 | // --------------------------------------------------------------------------------------------- | 218 | // --------------------------------------------------------------------------------------------- |
@@ -312,12 +374,12 @@ TEST_CASE("linda.multi Keeper") | |||
312 | 374 | ||
313 | S.requireSuccess("lanes = require 'lanes'.configure{nb_user_keepers = 3}"); | 375 | S.requireSuccess("lanes = require 'lanes'.configure{nb_user_keepers = 3}"); |
314 | 376 | ||
315 | S.requireFailure("lanes.linda(-1)"); | 377 | S.requireFailure("lanes.linda{group = -1}"); |
316 | S.requireSuccess("lanes.linda(0)"); | 378 | S.requireSuccess("lanes.linda{group = 0}"); |
317 | S.requireSuccess("lanes.linda(1)"); | 379 | S.requireSuccess("lanes.linda{group = 1}"); |
318 | S.requireSuccess("lanes.linda(2)"); | 380 | S.requireSuccess("lanes.linda{group = 2}"); |
319 | S.requireSuccess("lanes.linda(3)"); | 381 | S.requireSuccess("lanes.linda{group = 3}"); |
320 | S.requireFailure("lanes.linda(4)"); | 382 | S.requireFailure("lanes.linda{group = 4}"); |
321 | } | 383 | } |
322 | 384 | ||
323 | // ################################################################################################# | 385 | // ################################################################################################# |
@@ -327,23 +389,26 @@ TEST_CASE("linda.multi Keeper") | |||
327 | // so let's create a separate test case for each file with an ugly macro... | 389 | // so let's create a separate test case for each file with an ugly macro... |
328 | 390 | ||
329 | #define MAKE_TEST_CASE(DIR, FILE) \ | 391 | #define MAKE_TEST_CASE(DIR, FILE) \ |
330 | TEST_CASE("scripted tests." #DIR "." #FILE) \ | 392 | TEST_CASE("scripted_tests." #DIR "." #FILE) \ |
331 | { \ | 393 | { \ |
332 | FileRunner _runner(R"(.\unit_tests\scripts)"); \ | 394 | FileRunner _runner(R"(.\unit_tests\scripts)"); \ |
333 | _runner.performTest(FileRunnerParam{ #DIR "/" #FILE, TestType::AssertNoLuaError }); \ | 395 | _runner.performTest(FileRunnerParam{ #DIR "/" #FILE, TestType::AssertNoLuaError }); \ |
334 | } | 396 | } |
335 | 397 | ||
398 | MAKE_TEST_CASE(linda, multiple_keepers) | ||
336 | MAKE_TEST_CASE(linda, send_receive) | 399 | MAKE_TEST_CASE(linda, send_receive) |
400 | MAKE_TEST_CASE(linda, send_receive_func_and_string) | ||
337 | MAKE_TEST_CASE(linda, send_registered_userdata) | 401 | MAKE_TEST_CASE(linda, send_registered_userdata) |
338 | MAKE_TEST_CASE(linda, multiple_keepers) | 402 | MAKE_TEST_CASE(linda, wake_period) |
339 | 403 | ||
340 | /* | 404 | /* |
341 | TEST_CASE("linda.scripted tests") | 405 | TEST_CASE("linda.scripted_tests") |
342 | { | 406 | { |
343 | auto const& _testParam = GENERATE( | 407 | auto const& _testParam = GENERATE( |
408 | FileRunnerParam{ "linda/multiple_keepers", TestType::AssertNoLuaError }, | ||
344 | FileRunnerParam{ "linda/send_receive", TestType::AssertNoLuaError }, | 409 | FileRunnerParam{ "linda/send_receive", TestType::AssertNoLuaError }, |
345 | FileRunnerParam{ "linda/send_registered_userdata", TestType::AssertNoLuaError }, | 410 | FileRunnerParam{ "linda/send_registered_userdata", TestType::AssertNoLuaError }, |
346 | FileRunnerParam{ "linda/multiple_keepers", TestType::AssertNoLuaError } | 411 | FileRunnerParam{ "linda/wake_period", TestType::AssertNoLuaError } |
347 | ); | 412 | ); |
348 | 413 | ||
349 | FileRunner _runner(R"(.\unit_tests\scripts)"); | 414 | FileRunner _runner(R"(.\unit_tests\scripts)"); |