aboutsummaryrefslogtreecommitdiff
path: root/unit_tests/init_and_shutdown.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--unit_tests/init_and_shutdown.cpp1091
1 files changed, 553 insertions, 538 deletions
diff --git a/unit_tests/init_and_shutdown.cpp b/unit_tests/init_and_shutdown.cpp
index d45b52f..83c0350 100644
--- a/unit_tests/init_and_shutdown.cpp
+++ b/unit_tests/init_and_shutdown.cpp
@@ -3,14 +3,12 @@
3 3
4// ################################################################################################# 4// #################################################################################################
5 5
6TEST(Require, MissingBaseLibraries) 6TEST_CASE("require 'lanes'")
7{ 7{
8 LuaState L{ LuaState::WithBaseLibs{ false }, LuaState::WithFixture{ false } }; 8 LuaState L{ LuaState::WithBaseLibs{ false }, LuaState::WithFixture{ false } };
9 9
10 // no base library loaded means no print() 10 // no base library loaded means no print()
11 EXPECT_NE(L.doString("print('hello')"), LuaError::OK); 11 L.requireFailure("print('hello')");
12 L.stackCheck(1);
13 lua_pop(L, 1);
14 12
15 // need require() to require lanes 13 // need require() to require lanes
16 luaL_requiref(L, LUA_LOADLIBNAME, luaopen_package, 0); 14 luaL_requiref(L, LUA_LOADLIBNAME, luaopen_package, 0);
@@ -18,9 +16,7 @@ TEST(Require, MissingBaseLibraries)
18 L.stackCheck(0); 16 L.stackCheck(0);
19 17
20 // no base library loaded means lanes should issue an error 18 // no base library loaded means lanes should issue an error
21 EXPECT_NE(L.doString("require 'lanes'"), LuaError::OK); 19 L.requireFailure("require 'lanes'");
22 lua_pop(L, 1);
23 L.stackCheck(0);
24 20
25 // need base to make lanes happy 21 // need base to make lanes happy
26 luaL_requiref(L, LUA_GNAME, luaopen_base, 1); 22 luaL_requiref(L, LUA_GNAME, luaopen_base, 1);
@@ -28,9 +24,7 @@ TEST(Require, MissingBaseLibraries)
28 L.stackCheck(0); 24 L.stackCheck(0);
29 25
30 // no table library loaded means lanes should issue an error 26 // no table library loaded means lanes should issue an error
31 EXPECT_NE(L.doString("require 'lanes'"), LuaError::OK); 27 L.requireFailure("require 'lanes'");
32 L.stackCheck(1);
33 lua_pop(L, 1);
34 28
35 // need table to make lanes happy 29 // need table to make lanes happy
36 luaL_requiref(L, LUA_TABLIBNAME, luaopen_table, 1); 30 luaL_requiref(L, LUA_TABLIBNAME, luaopen_table, 1);
@@ -38,9 +32,7 @@ TEST(Require, MissingBaseLibraries)
38 L.stackCheck(0); 32 L.stackCheck(0);
39 33
40 // no string library loaded means lanes should issue an error 34 // no string library loaded means lanes should issue an error
41 EXPECT_NE(L.doString("require 'lanes'"), LuaError::OK); 35 L.requireFailure("require 'lanes'");
42 lua_pop(L, 1);
43 L.stackCheck(0);
44 36
45 // need string to make lanes happy 37 // need string to make lanes happy
46 luaL_requiref(L, LUA_STRLIBNAME, luaopen_string, 1); 38 luaL_requiref(L, LUA_STRLIBNAME, luaopen_string, 1);
@@ -50,7 +42,7 @@ TEST(Require, MissingBaseLibraries)
50 // all required libraries are here: we should be happy 42 // all required libraries are here: we should be happy
51 // that's only the case for Lua > 5.1 though, because the latter can't require() a module after a previously failed attempt (like we just did) 43 // that's only the case for Lua > 5.1 though, because the latter can't require() a module after a previously failed attempt (like we just did)
52 if constexpr (LUA_VERSION_NUM > 501) { 44 if constexpr (LUA_VERSION_NUM > 501) {
53 ASSERT_EQ(L.doString("require 'lanes'"), LuaError::OK); 45 L.requireSuccess("require 'lanes'");
54 } else { 46 } else {
55 // so let's do a fresh attempt in a virgin state where we have the 3 base libraries we need (plus 'package' to be able to require it of course) 47 // so let's do a fresh attempt in a virgin state where we have the 3 base libraries we need (plus 'package' to be able to require it of course)
56 LuaState L51{ LuaState::WithBaseLibs{ false }, LuaState::WithFixture{ false } }; 48 LuaState L51{ LuaState::WithBaseLibs{ false }, LuaState::WithFixture{ false } };
@@ -59,625 +51,653 @@ TEST(Require, MissingBaseLibraries)
59 luaL_requiref(L51, LUA_TABLIBNAME, luaopen_table, 1); 51 luaL_requiref(L51, LUA_TABLIBNAME, luaopen_table, 1);
60 luaL_requiref(L51, LUA_STRLIBNAME, luaopen_string, 1); 52 luaL_requiref(L51, LUA_STRLIBNAME, luaopen_string, 1);
61 lua_settop(L51, 0); 53 lua_settop(L51, 0);
62 ASSERT_EQ(L51.doString("require 'lanes'"), LuaError::OK); 54 L51.requireSuccess("require 'lanes'");
63 } 55 }
64} 56}
65 57
66class Configure : public ::testing::Test
67{
68 protected:
69 LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
70};
71
72// ################################################################################################# 58// #################################################################################################
73// ################################################################################################# 59// #################################################################################################
74// allocator should be "protected", a C function returning a suitable userdata, or nil 60// allocator should be "protected", a C function returning a suitable userdata, or nil
75 61
76TEST_F(Configure, AllocatorFalse) 62TEST_CASE("lanes.configure")
77{ 63{
78 EXPECT_NE(L.doString("require 'lanes'.configure{allocator = false}"), LuaError::OK); 64 LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
79}
80 65
81// ################################################################################################# 66 // ---------------------------------------------------------------------------------------------
82 67
83TEST_F(Configure, AllocatorTrue) 68 SECTION("allocator", "[allocator]")
84{ 69 {
85 EXPECT_NE(L.doString("require 'lanes'.configure{allocator = true}"), LuaError::OK); 70 SECTION("allocator = false")
86} 71 {
72 L.requireFailure("require 'lanes'.configure{allocator = false}");
73 }
87 74
88// ################################################################################################# 75 // -----------------------------------------------------------------------------------------
89 76
90TEST_F(Configure, AllocatorNumber) 77 SECTION("allocator = true")
91{ 78 {
92 EXPECT_NE(L.doString("require 'lanes'.configure{allocator = 33}"), LuaError::OK); 79 L.requireFailure("require 'lanes'.configure{allocator = true}");
93} 80 }
94 81
95// ################################################################################################# 82 // -----------------------------------------------------------------------------------------
96 83
97TEST_F(Configure, AllocatorTable) 84 SECTION("allocator = <number>")
98{ 85 {
99 EXPECT_NE(L.doString("require 'lanes'.configure{allocator = {}}"), LuaError::OK); 86 L.requireFailure("require 'lanes'.configure{allocator = 33}");
100} 87 }
101 88
102// ################################################################################################# 89 // -----------------------------------------------------------------------------------------
103 90
104TEST_F(Configure, AllocatorLuaFunction) 91 SECTION("allocator = <table>")
105{ 92 {
106 EXPECT_NE(L.doString("require 'lanes'.configure{allocator = function() return {}, 12, 'yoy' end}"), LuaError::OK); 93 L.requireFailure("require 'lanes'.configure{allocator = {}}");
107} 94 }
108 95
109// ################################################################################################# 96 // -----------------------------------------------------------------------------------------
110 97
111TEST_F(Configure, AllocatorBadCFunction) 98 SECTION("allocator = <Lua function>")
112{ 99 {
113 // a C function that doesn't return what we expect should cause an error too 100 L.requireFailure("require 'lanes'.configure{allocator = function() return {}, 12, 'yoy' end}");
114 EXPECT_NE(L.doString("require 'lanes'.configure{allocator = print}"), LuaError::OK); 101 }
115}
116 102
117// ################################################################################################# 103 // -----------------------------------------------------------------------------------------
118 104
119TEST_F(Configure, AllocatorTypo) 105 SECTION("allocator = <bad C function>")
120{ 106 {
121 // oops, a typo 107 // a C function that doesn't return what we expect should cause an error too
122 EXPECT_NE(L.doString("require 'lanes'.configure{allocator = 'Protected'}"), LuaError::OK); 108 L.requireFailure("require 'lanes'.configure{allocator = print}");
123} 109 }
124 110
125// ################################################################################################# 111 // -----------------------------------------------------------------------------------------
126 112
127TEST_F(Configure, AllocatorProtected) 113 SECTION("allocator = <string with a typo>")
128{ 114 {
129 // no typo, should work 115 // oops, a typo
130 EXPECT_EQ(L.doString("require 'lanes'.configure{allocator = 'protected'}"), LuaError::OK); 116 L.requireFailure("require 'lanes'.configure{allocator = 'Protected'}");
131} 117 }
132 118
133// ################################################################################################# 119 // -----------------------------------------------------------------------------------------
134 120
135TEST_F(Configure, AllocatorCustomOk) 121 SECTION("allocator = 'protected'")
136{ 122 {
137 // a function that provides what we expect is fine 123 // no typo, should work
138 static constexpr lua_CFunction _provideAllocator = +[](lua_State* const L_) { 124 L.requireSuccess("require 'lanes'.configure{allocator = 'protected'}");
139 lanes::AllocatorDefinition* const _def{ new (L_) lanes::AllocatorDefinition{} }; 125 }
140 _def->initFrom(L_);
141 return 1;
142 };
143 lua_pushcfunction(L, _provideAllocator);
144 lua_setglobal(L, "ProvideAllocator");
145 EXPECT_EQ(L.doString("require 'lanes'.configure{allocator = ProvideAllocator}"), LuaError::OK);
146}
147 126
148// ################################################################################################# 127 // -----------------------------------------------------------------------------------------
149 128
150TEST_F(Configure, AllocatorCustomWrongResultType) 129 SECTION("allocator = <good custom C allocator>")
151{ 130 {
152 // a function that provides something that is definitely not an AllocatorDefinition, should cause an error 131 // a function that provides what we expect is fine
153 static constexpr lua_CFunction _provideAllocator = +[](lua_State* const L_) { 132 static constexpr lua_CFunction _provideAllocator = +[](lua_State* const L_) {
154 lua_newtable(L_); 133 lanes::AllocatorDefinition* const _def{ new (L_) lanes::AllocatorDefinition{} };
155 return 1; 134 _def->initFrom(L_);
156 }; 135 return 1;
157 lua_pushcfunction(L, _provideAllocator); 136 };
158 lua_setglobal(L, "ProvideAllocator"); 137 lua_pushcfunction(L, _provideAllocator);
159 EXPECT_NE(L.doString("require 'lanes'.configure{allocator = ProvideAllocator}"), LuaError::OK); 138 lua_setglobal(L, "ProvideAllocator");
160} 139 L.requireSuccess("require 'lanes'.configure{allocator = ProvideAllocator}");
140 }
161 141
162// ################################################################################################# 142 // -----------------------------------------------------------------------------------------
163 143
164TEST_F(Configure, AllocatorCustomSignatureMismatch) 144 SECTION("allocator not returning an AllocatorDefinition")
165{ 145 {
166 // a function that provides something that is too small to contain an AllocatorDefinition, should cause an error 146 // a function that provides something that is definitely not an AllocatorDefinition, should cause an error
167 static constexpr lua_CFunction _provideAllocator = +[](lua_State* const L_) { 147 static constexpr lua_CFunction _provideAllocator = +[](lua_State* const L_) {
168 // create a full userdata that is too small (it only contains enough to store a version tag, but not the rest 148 lua_newtable(L_);
169 auto* const _duck{ static_cast<lanes::AllocatorDefinition::version_t*>(lua_newuserdata(L_, sizeof(lanes::AllocatorDefinition::version_t))) }; 149 return 1;
170 *_duck = 666777; 150 };
171 return 1; 151 lua_pushcfunction(L, _provideAllocator);
172 }; 152 lua_setglobal(L, "ProvideAllocator");
173 lua_pushcfunction(L, _provideAllocator); 153 L.requireFailure("require 'lanes'.configure{allocator = ProvideAllocator}");
174 lua_setglobal(L, "ProvideAllocator"); 154 }
175 EXPECT_NE(L.doString("require 'lanes'.configure{allocator = ProvideAllocator}"), LuaError::OK);
176}
177 155
178// ################################################################################################# 156 // -----------------------------------------------------------------------------------------
179 157
180TEST_F(Configure, AllocatorCustomSizeMismatch) 158 SECTION("allocator returning an AllocatorDefinition with the wrong signature")
181{ 159 {
182 // a function that provides something that attempts to pass as an AllocatorDefinition, but is not, should cause an error 160 // a function that provides something that is too small to contain an AllocatorDefinition, should cause an error
183 static constexpr lua_CFunction _provideAllocator = +[](lua_State* const L_) { 161 static constexpr lua_CFunction _provideAllocator = +[](lua_State* const L_) {
184 // create a full userdata of the correct size, but of course the contents don't match 162 // create a full userdata that is too small (it only contains enough to store a version tag, but not the rest
185 int* const _duck{ static_cast<int*>(lua_newuserdata(L_, sizeof(lanes::AllocatorDefinition))) }; 163 auto* const _duck{ static_cast<lanes::AllocatorDefinition::version_t*>(lua_newuserdata(L_, sizeof(lanes::AllocatorDefinition::version_t))) };
186 _duck[0] = 666; 164 *_duck = 666777;
187 _duck[1] = 777; 165 return 1;
188 return 1; 166 };
189 }; 167 lua_pushcfunction(L, _provideAllocator);
190 lua_pushcfunction(L, _provideAllocator); 168 lua_setglobal(L, "ProvideAllocator");
191 lua_setglobal(L, "ProvideAllocator"); 169 L.requireFailure("require 'lanes'.configure{allocator = ProvideAllocator}");
192 EXPECT_NE(L.doString("require 'lanes'.configure{allocator = ProvideAllocator}"), LuaError::OK); 170 }
193}
194 171
195// ################################################################################################# 172 // -----------------------------------------------------------------------------------------
196// #################################################################################################
197// internal_allocator should be a string, "libc"/"allocator"
198 173
199TEST_F(Configure, InternalAllocatorFalse) 174 SECTION("allocator returning something too small to be a valid AllocatorDefinition")
200{ 175 {
201 EXPECT_NE(L.doString("require 'lanes'.configure{internal_allocator = false}"), LuaError::OK); 176 // a function that provides something that attempts to pass as an AllocatorDefinition, but is not, should cause an error
202} 177 static constexpr lua_CFunction _provideAllocator = +[](lua_State* const L_) {
178 // create a full userdata of the correct size, but of course the contents don't match
179 int* const _duck{ static_cast<int*>(lua_newuserdata(L_, sizeof(lanes::AllocatorDefinition))) };
180 _duck[0] = 666;
181 _duck[1] = 777;
182 return 1;
183 };
184 lua_pushcfunction(L, _provideAllocator);
185 lua_setglobal(L, "ProvideAllocator");
186 L.requireFailure("require 'lanes'.configure{allocator = ProvideAllocator}");
187 }
188 }
203 189
204// ################################################################################################# 190 // ---------------------------------------------------------------------------------------------
191 // internal_allocator should be a string, "libc"/"allocator"
205 192
206TEST_F(Configure, InternalAllocatorTrue) 193 SECTION("[internal_allocator")
207{ 194 {
208 EXPECT_NE(L.doString("require 'lanes'.configure{internal_allocator = true}"), LuaError::OK); 195 SECTION("internal_allocator = false")
209} 196 {
197 L.requireFailure("require 'lanes'.configure{internal_allocator = false}");
198 }
210 199
211// ################################################################################################# 200 // -----------------------------------------------------------------------------------------
212 201
213TEST_F(Configure, InternalAllocatorTable) 202 SECTION("internal_allocator = true")
214{ 203 {
215 EXPECT_NE(L.doString("require 'lanes'.configure{internal_allocator = {}}"), LuaError::OK); 204 L.requireFailure("require 'lanes'.configure{internal_allocator = true}");
216} 205 }
217 206
218// ################################################################################################# 207 // -----------------------------------------------------------------------------------------
219 208
220TEST_F(Configure, InternalAllocatorFunction) 209 SECTION("internal_allocator = <table>")
221{ 210 {
222 EXPECT_NE(L.doString("require 'lanes'.configure{internal_allocator = function() end}"), LuaError::OK); 211 L.requireFailure("require 'lanes'.configure{internal_allocator = {}}");
223} 212 }
224 213
225// ################################################################################################# 214 // -----------------------------------------------------------------------------------------
226 215
227TEST_F(Configure, InternalAllocatorString) 216 SECTION("internal_allocator = <Lua function>")
228{ 217 {
229 EXPECT_NE(L.doString("require 'lanes'.configure{internal_allocator = 'gluh'}"), LuaError::OK); 218 L.requireFailure("require 'lanes'.configure{internal_allocator = function() end}");
230} 219 }
231 220
232// ################################################################################################# 221 // -----------------------------------------------------------------------------------------
233 222
234TEST_F(Configure, InternalAllocatorLibc) 223 SECTION("internal_allocator = <bad string>")
235{ 224 {
236 EXPECT_EQ(L.doString("require 'lanes'.configure{internal_allocator = 'libc'}"), LuaError::OK); 225 L.requireFailure("require 'lanes'.configure{internal_allocator = 'gluh'}");
237} 226 }
238 227
239// ################################################################################################# 228 // -----------------------------------------------------------------------------------------
240 229
241TEST_F(Configure, InternalAllocatorAllocator) 230 SECTION("internal_allocator = 'libc'")
242{ 231 {
243 EXPECT_EQ(L.doString("require 'lanes'.configure{internal_allocator = 'allocator'}"), LuaError::OK); 232 L.requireSuccess("require 'lanes'.configure{internal_allocator = 'libc'}");
244} 233 }
245 234
246// ################################################################################################# 235 // -----------------------------------------------------------------------------------------
247// #################################################################################################
248// keepers_gc_threshold should be a number in [0, 100]
249 236
250TEST_F(Configure, KeepersGcThresholdTable) 237 SECTION("internal_allocator = 'allocator'")
251{ 238 {
252 EXPECT_NE(L.doString("require 'lanes'.configure{keepers_gc_threshold = {}}"), LuaError::OK); 239 L.requireSuccess("require 'lanes'.configure{internal_allocator = 'allocator'}");
253} 240 }
241 }
254 242
255// ################################################################################################# 243 // ---------------------------------------------------------------------------------------------
244 // keepers_gc_threshold should be a number in [0, 100]
256 245
257TEST_F(Configure, KeepersGcThresholdString) 246 SECTION("keepers_gc_threshold")
258{ 247 {
259 EXPECT_NE(L.doString("require 'lanes'.configure{keepers_gc_threshold = 'gluh'}"), LuaError::OK); 248 SECTION("keepers_gc_threshold = <table>")
260} 249 {
250 L.requireFailure("require 'lanes'.configure{keepers_gc_threshold = {}}");
251 }
261 252
262// ################################################################################################# 253 // -----------------------------------------------------------------------------------------
263 254
264TEST_F(Configure, KeepersGcThresholdNegative) 255 SECTION("keepers_gc_threshold = <string>")
265{ 256 {
266 EXPECT_EQ(L.doString("require 'lanes'.configure{keepers_gc_threshold = -1}"), LuaError::OK); 257 L.requireFailure("require 'lanes'.configure{keepers_gc_threshold = 'gluh'}");
267} 258 }
268 259
269// ################################################################################################# 260 // -----------------------------------------------------------------------------------------
270 261
271TEST_F(Configure, KeepersGcThresholdZero) 262 SECTION("keepers_gc_threshold = -1")
272{ 263 {
273 EXPECT_EQ(L.doString("require 'lanes'.configure{keepers_gc_threshold = 0}"), LuaError::OK); 264 L.requireSuccess("require 'lanes'.configure{keepers_gc_threshold = -1}");
274} 265 }
275 266
276// ################################################################################################# 267 // -----------------------------------------------------------------------------------------
277 268
278TEST_F(Configure, KeepersGcThresholdHundred) 269 SECTION("keepers_gc_threshold = 0")
279{ 270 {
280 EXPECT_EQ(L.doString("require 'lanes'.configure{keepers_gc_threshold = 100}"), LuaError::OK); 271 L.requireSuccess("require 'lanes'.configure{keepers_gc_threshold = 0}");
281} 272 }
282 273
283// ################################################################################################# 274 // -----------------------------------------------------------------------------------------
284// #################################################################################################
285// nb_user_keepers should be a number in [0, 100]
286 275
287TEST_F(Configure, NbUserKeepersTable) 276 SECTION("keepers_gc_threshold = 100")
288{ 277 {
289 EXPECT_NE(L.doString("require 'lanes'.configure{nb_user_keepers = {}}"), LuaError::OK); 278 L.requireSuccess("require 'lanes'.configure{keepers_gc_threshold = 100}");
290} 279 }
280 }
291 281
292// ################################################################################################# 282 // ---------------------------------------------------------------------------------------------
283 // nb_user_keepers should be a number in [0, 100]
293 284
294TEST_F(Configure, NbUserKeepersString) 285 SECTION("nb_user_keepers")
295{ 286 {
296 EXPECT_NE(L.doString("require 'lanes'.configure{nb_user_keepers = 'gluh'}"), LuaError::OK); 287 SECTION("nb_user_keepers = <table>")
297} 288 {
289 L.requireFailure("require 'lanes'.configure{nb_user_keepers = {}}");
290 }
298 291
299// ################################################################################################# 292 // -----------------------------------------------------------------------------------------
300 293
301TEST_F(Configure, NbUserKeepersNegative) 294 SECTION("nb_user_keepers = <string>")
302{ 295 {
303 EXPECT_NE(L.doString("require 'lanes'.configure{nb_user_keepers = -1}"), LuaError::OK); 296 L.requireFailure("require 'lanes'.configure{nb_user_keepers = 'gluh'}");
304} 297 }
305 298
306// ################################################################################################# 299 // -----------------------------------------------------------------------------------------
307 300
308TEST_F(Configure, NbUserKeepersZero) 301 SECTION("nb_user_keepers = -1")
309{ 302 {
310 EXPECT_EQ(L.doString("require 'lanes'.configure{nb_user_keepers = 0}"), LuaError::OK); 303 L.requireFailure("require 'lanes'.configure{nb_user_keepers = -1}");
311} 304 }
312 305
313// ################################################################################################# 306 // -----------------------------------------------------------------------------------------
314 307
315TEST_F(Configure, NbUserKeepersHundred) 308 SECTION("nb_user_keepers = 0")
316{ 309 {
317 EXPECT_EQ(L.doString("require 'lanes'.configure{nb_user_keepers = 100}"), LuaError::OK); 310 L.requireSuccess("require 'lanes'.configure{nb_user_keepers = 0}");
318} 311 }
319 312
320// ################################################################################################# 313 // -----------------------------------------------------------------------------------------
321 314
322TEST_F(Configure, NbUserKeepersHundredAndOne) 315 SECTION("nb_user_keepers = 100")
323{ 316 {
324 EXPECT_NE(L.doString("require 'lanes'.configure{nb_user_keepers = 101}"), LuaError::OK); 317 L.requireSuccess("require 'lanes'.configure{nb_user_keepers = 100}");
325} 318 }
326 319
327// ################################################################################################# 320 // -----------------------------------------------------------------------------------------
328// #################################################################################################
329// on_state_create should be a function, either C or Lua, without upvalues
330 321
331TEST_F(Configure, OnStateCreateTable) 322 SECTION("nb_user_keepers = 101")
332{ 323 {
333 EXPECT_NE(L.doString("require 'lanes'.configure{on_state_create = {}}"), LuaError::OK); 324 L.requireFailure("require 'lanes'.configure{nb_user_keepers = 101}");
334} 325 }
326 }
335 327
336// ################################################################################################# 328 // ---------------------------------------------------------------------------------------------
329 // on_state_create should be a function, either C or Lua, without upvalues
337 330
338TEST_F(Configure, OnStateCreateString) 331 SECTION("on_state_create")
339{ 332 {
340 EXPECT_NE(L.doString("require 'lanes'.configure{on_state_create = 'gluh'}"), LuaError::OK); 333 SECTION("on_state_create = <table>")
341} 334 {
335 L.requireFailure("require 'lanes'.configure{on_state_create = {}}");
336 }
342 337
343// ################################################################################################# 338 // -----------------------------------------------------------------------------------------
344 339
345TEST_F(Configure, OnStateCreateNumber) 340 SECTION("on_state_create = <string>")
346{ 341 {
347 EXPECT_NE(L.doString("require 'lanes'.configure{on_state_create = 1}"), LuaError::OK); 342 L.requireFailure("require 'lanes'.configure{on_state_create = 'gluh'}");
348} 343 }
349 344
350// ################################################################################################# 345 // -----------------------------------------------------------------------------------------
351 346
352TEST_F(Configure, OnStateCreateFalse) 347 SECTION("on_state_create = <number>")
353{ 348 {
354 EXPECT_NE(L.doString("require 'lanes'.configure{on_state_create = false}"), LuaError::OK); 349 L.requireFailure("require 'lanes'.configure{on_state_create = 1}");
355} 350 }
356 351
357// ################################################################################################# 352 // -----------------------------------------------------------------------------------------
358 353
359TEST_F(Configure, OnStateCreateTrue) 354 SECTION("on_state_create = false")
360{ 355 {
361 EXPECT_NE(L.doString("require 'lanes'.configure{on_state_create = true}"), LuaError::OK); 356 L.requireFailure("require 'lanes'.configure{on_state_create = false}");
362} 357 }
363 358
364// ################################################################################################# 359 // -----------------------------------------------------------------------------------------
365 360
366TEST_F(Configure, OnStateCreateUpvaluedFunction) 361 SECTION("on_state_create = true")
367{ 362 {
368 // 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!) 363 L.requireFailure("require 'lanes'.configure{on_state_create = true}");
369 EXPECT_EQ(L.doString("local print = print; require 'lanes'.configure{on_state_create = function() print 'hello' end}"), LuaError::OK); 364 }
370}
371 365
372// ################################################################################################# 366 // -----------------------------------------------------------------------------------------
373 367
374TEST_F(Configure, OnStateCreateCFunction) 368 SECTION("on_state_create = <Lua function>")
375{ 369 {
376 // 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" 370 // 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!)
377 // conclusion, don't use print() as a fake on_state_create() callback! 371 L.requireSuccess("local print = print; require 'lanes'.configure{on_state_create = function() print 'hello' end}");
378 // assert() should be fine since we pass a non-false argument to on_state_create 372 }
379 EXPECT_EQ(L.doString("require 'lanes'.configure{on_state_create = assert}"), LuaError::OK);
380}
381 373
382// ################################################################################################# 374 // -----------------------------------------------------------------------------------------
383// #################################################################################################
384// shutdown_timeout should be a number in [0,3600]
385 375
386TEST_F(Configure, ShutdownTimeoutTable) 376 SECTION("on_state_create = <C function>")
387{ 377 {
388 EXPECT_NE(L.doString("require 'lanes'.configure{shutdown_timeout = {}}"), LuaError::OK); 378 // 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"
389} 379 // conclusion, don't use print() as a fake on_state_create() callback!
380 // assert() should be fine since we pass a non-false argument to on_state_create
381 L.requireSuccess("require 'lanes'.configure{on_state_create = assert}");
382 }
383 }
390 384
391// ################################################################################################# 385 // ---------------------------------------------------------------------------------------------
386 // shutdown_timeout should be a number in [0,3600]
392 387
393TEST_F(Configure, ShutdownTimeoutString) 388 SECTION("shutdown_timeout")
394{ 389 {
395 EXPECT_NE(L.doString("require 'lanes'.configure{shutdown_timeout = 'gluh'}"), LuaError::OK); 390 SECTION("shutdown_timeout = <table>")
396} 391 {
392 L.requireFailure("require 'lanes'.configure{shutdown_timeout = {}}");
393 }
397 394
398// ################################################################################################# 395 // -----------------------------------------------------------------------------------------
399 396
400TEST_F(Configure, ShutdownTimeoutNegative) 397 SECTION("shutdown_timeout = <string>")
401{ 398 {
402 EXPECT_NE(L.doString("require 'lanes'.configure{shutdown_timeout = -0.001}"), LuaError::OK); 399 L.requireFailure("require 'lanes'.configure{shutdown_timeout = 'gluh'}");
403} 400 }
404 401
405// ################################################################################################# 402 // -----------------------------------------------------------------------------------------
406 403
407TEST_F(Configure, ShutdownTimeoutZero) 404 SECTION("shutdown_timeout = <negative number>")
408{ 405 {
409 EXPECT_EQ(L.doString("require 'lanes'.configure{shutdown_timeout = 0}"), LuaError::OK); 406 L.requireFailure("require 'lanes'.configure{shutdown_timeout = -0.001}");
410} 407 }
411 408
412// ################################################################################################# 409 // -----------------------------------------------------------------------------------------
413 410
414TEST_F(Configure, ShutdownTimeoutOne) 411 SECTION("shutdown_timeout = 0")
415{ 412 {
416 EXPECT_EQ(L.doString("require 'lanes'.configure{shutdown_timeout = 1}"), LuaError::OK); 413 L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 0}");
417} 414 }
418 415
419// ################################################################################################# 416 // -----------------------------------------------------------------------------------------
420 417
421TEST_F(Configure, ShutdownTimeoutHour) 418 SECTION("shutdown_timeout = 1s")
422{ 419 {
423 EXPECT_EQ(L.doString("require 'lanes'.configure{shutdown_timeout = 3600}"), LuaError::OK); 420 L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 1}");
424} 421 }
425 422
426// ################################################################################################# 423 // -----------------------------------------------------------------------------------------
427 424
428TEST_F(Configure, ShutdownTimeoutTooLong) 425 SECTION("shutdown_timeout = 3600s")
429{ 426 {
430 EXPECT_NE(L.doString("require 'lanes'.configure{shutdown_timeout = 3600.001}"), LuaError::OK); 427 L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 3600}");
431} 428 }
432 429
433// ################################################################################################# 430 // -----------------------------------------------------------------------------------------
434// #################################################################################################
435// strip_functions should be a boolean
436 431
437TEST_F(Configure, StripFunctionsTable) 432 SECTION("shutdown_timeout = <too long>")
438{ 433 {
439 EXPECT_NE(L.doString("require 'lanes'.configure{strip_functions = {}}"), LuaError::OK); 434 L.requireFailure("require 'lanes'.configure{shutdown_timeout = 3600.001}");
440} 435 }
436 }
441 437
442// ################################################################################################# 438 // ---------------------------------------------------------------------------------------------
439 // strip_functions should be a boolean
443 440
444TEST_F(Configure, StripFunctionsString) 441 SECTION("strip_functions")
445{ 442 {
446 EXPECT_NE(L.doString("require 'lanes'.configure{strip_functions = 'gluh'}"), LuaError::OK); 443 SECTION("strip_functions = <table>")
447} 444 {
445 L.requireFailure("require 'lanes'.configure{strip_functions = {}}");
446 }
448 447
449// ################################################################################################# 448 // -----------------------------------------------------------------------------------------
450 449
451TEST_F(Configure, StripFunctionsNumber) 450 SECTION("strip_functions = <string>")
452{ 451 {
453 EXPECT_NE(L.doString("require 'lanes'.configure{strip_functions = 1}"), LuaError::OK); 452 L.requireFailure("require 'lanes'.configure{strip_functions = 'gluh'}");
454} 453 }
455 454
456// ################################################################################################# 455 // -----------------------------------------------------------------------------------------
457 456
458TEST_F(Configure, StripFunctionsFunction) 457 SECTION("strip_functions = <number>")
459{ 458 {
460 EXPECT_NE(L.doString("require 'lanes'.configure{strip_functions = print}"), LuaError::OK); 459 L.requireFailure("require 'lanes'.configure{strip_functions = 1}");
461} 460 }
462 461
463// ################################################################################################# 462 // -----------------------------------------------------------------------------------------
464 463
465TEST_F(Configure, StripFunctionsFalse) 464 SECTION("strip_functions = <C function>")
466{ 465 {
467 EXPECT_EQ(L.doString("require 'lanes'.configure{strip_functions = false}"), LuaError::OK); 466 L.requireFailure("require 'lanes'.configure{strip_functions = print}");
468} 467 }
469 468
470// ################################################################################################# 469 // -----------------------------------------------------------------------------------------
471 470
472TEST_F(Configure, StripFunctionsTrue) 471 SECTION("strip_functions = false")
473{ 472 {
474 EXPECT_EQ(L.doString("require 'lanes'.configure{strip_functions = true}"), LuaError::OK); 473 L.requireSuccess("require 'lanes'.configure{strip_functions = false}");
475} 474 }
476 475
477// ################################################################################################# 476 // -----------------------------------------------------------------------------------------
478// #################################################################################################
479// track_lanes should be a boolean
480 477
481TEST_F(Configure, TrackLanesTable) 478 SECTION("strip_functions = true")
482{ 479 {
483 EXPECT_NE(L.doString("require 'lanes'.configure{track_lanes = {}}"), LuaError::OK); 480 L.requireSuccess("require 'lanes'.configure{strip_functions = true}");
484} 481 }
482 }
485 483
486// ################################################################################################# 484 // ---------------------------------------------------------------------------------------------
485 // track_lanes should be a boolean
487 486
488TEST_F(Configure, TrackLanesString) 487 SECTION("track_lanes")
489{ 488 {
490 EXPECT_NE(L.doString("require 'lanes'.configure{track_lanes = 'gluh'}"), LuaError::OK); 489 SECTION("track_lanes = <table>")
491} 490 {
491 L.requireFailure("require 'lanes'.configure{track_lanes = {}}");
492 }
492 493
493// ################################################################################################# 494 // -----------------------------------------------------------------------------------------
494 495
495TEST_F(Configure, TrackLanesNumber) 496 SECTION("track_lanes = <string>")
496{ 497 {
497 EXPECT_NE(L.doString("require 'lanes'.configure{track_lanes = 1}"), LuaError::OK); 498 L.requireFailure("require 'lanes'.configure{track_lanes = 'gluh'}");
498} 499 }
499 500
500// ################################################################################################# 501 // -----------------------------------------------------------------------------------------
501 502
502TEST_F(Configure, TrackLanesFunction) 503 SECTION("track_lanes = <number>")
503{ 504 {
504 EXPECT_NE(L.doString("require 'lanes'.configure{track_lanes = print}"), LuaError::OK); 505 L.requireFailure("require 'lanes'.configure{track_lanes = 1}");
505} 506 }
506 507
507// ################################################################################################# 508 // -----------------------------------------------------------------------------------------
508 509
509TEST_F(Configure, TrackLanesFalse) 510 SECTION("track_lanes = <C function>")
510{ 511 {
511 EXPECT_EQ(L.doString("require 'lanes'.configure{track_lanes = false}"), LuaError::OK); 512 L.requireFailure("require 'lanes'.configure{track_lanes = print}");
512} 513 }
513 514
514// ################################################################################################# 515 // -----------------------------------------------------------------------------------------
515 516
516TEST_F(Configure, TrackLanesTrue) 517 SECTION("track_lanes = false")
517{ 518 {
518 EXPECT_EQ(L.doString("require 'lanes'.configure{track_lanes = true}"), LuaError::OK); 519 L.requireSuccess("require 'lanes'.configure{track_lanes = false}");
519} 520 }
520 521
521// ################################################################################################# 522 // -----------------------------------------------------------------------------------------
522// #################################################################################################
523// verbose_errors should be a boolean
524 523
525TEST_F(Configure, VerboseErrorsTable) 524 SECTION("track_lanes = true")
526{ 525 {
527 EXPECT_NE(L.doString("require 'lanes'.configure{verbose_errors = {}}"), LuaError::OK); 526 L.requireSuccess("require 'lanes'.configure{track_lanes = true}");
528} 527 }
528 }
529 529
530// ################################################################################################# 530 // ---------------------------------------------------------------------------------------------
531 // verbose_errors should be a boolean
531 532
532TEST_F(Configure, VerboseErrorsString) 533 SECTION("verbose_errors")
533{ 534 {
534 EXPECT_NE(L.doString("require 'lanes'.configure{verbose_errors = 'gluh'}"), LuaError::OK); 535 SECTION("verbose_errors = <table>")
535} 536 {
537 L.requireFailure("require 'lanes'.configure{verbose_errors = {}}");
538 }
536 539
537// ################################################################################################# 540 // -----------------------------------------------------------------------------------------
538 541
539TEST_F(Configure, VerboseErrorsNumber) 542 SECTION("verbose_errors = <string>")
540{ 543 {
541 EXPECT_NE(L.doString("require 'lanes'.configure{verbose_errors = 1}"), LuaError::OK); 544 L.requireFailure("require 'lanes'.configure{verbose_errors = 'gluh'}");
542} 545 }
543 546
544// ################################################################################################# 547 // -----------------------------------------------------------------------------------------
545 548
546TEST_F(Configure, VerboseErrorsFunction) 549 SECTION("verbose_errors = <number>")
547{ 550 {
548 EXPECT_NE(L.doString("require 'lanes'.configure{verbose_errors = print}"), LuaError::OK); 551 L.requireFailure("require 'lanes'.configure{verbose_errors = 1}");
549} 552 }
550 553
551// ################################################################################################# 554 // -----------------------------------------------------------------------------------------
552 555
553TEST_F(Configure, VerboseErrorsFalse) 556 SECTION("verbose_errors = <C function>")
554{ 557 {
555 EXPECT_EQ(L.doString("require 'lanes'.configure{verbose_errors = false}"), LuaError::OK); 558 L.requireFailure("require 'lanes'.configure{verbose_errors = print}");
556} 559 }
557 560
558// ################################################################################################# 561 // -----------------------------------------------------------------------------------------
559 562
560TEST_F(Configure, VerboseErrorsTrue) 563 SECTION("verbose_errors = false")
561{ 564 {
562 EXPECT_EQ(L.doString("require 'lanes'.configure{verbose_errors = true}"), LuaError::OK); 565 L.requireSuccess("require 'lanes'.configure{verbose_errors = false}");
563} 566 }
564 567
565// ################################################################################################# 568 // -----------------------------------------------------------------------------------------
566// #################################################################################################
567// with_timers should be a boolean
568 569
569TEST_F(Configure, WithTimersTable) 570 SECTION("verbose_errors = true")
570{ 571 {
571 EXPECT_NE(L.doString("require 'lanes'.configure{with_timers = {}}"), LuaError::OK); 572 L.requireSuccess("require 'lanes'.configure{verbose_errors = true}");
572} 573 }
574 }
573 575
574// ################################################################################################# 576 // ---------------------------------------------------------------------------------------------
577 // with_timers should be a boolean
575 578
576TEST_F(Configure, WithTimersString) 579 SECTION("with_timers")
577{ 580 {
578 EXPECT_NE(L.doString("require 'lanes'.configure{with_timers = 'gluh'}"), LuaError::OK); 581 SECTION("with_timers = <table>")
579} 582 {
583 L.requireFailure("require 'lanes'.configure{with_timers = {}}");
584 }
580 585
581// ################################################################################################# 586 // -----------------------------------------------------------------------------------------
582 587
583TEST_F(Configure, WithTimersNumber) 588 SECTION("with_timers = <string>")
584{ 589 {
585 EXPECT_NE(L.doString("require 'lanes'.configure{with_timers = 1}"), LuaError::OK); 590 L.requireFailure("require 'lanes'.configure{with_timers = 'gluh'}");
586} 591 }
587 592
588// ################################################################################################# 593 // -----------------------------------------------------------------------------------------
589 594
590TEST_F(Configure, WithTimersFunction) 595 SECTION("with_timers = <number>")
591{ 596 {
592 EXPECT_NE(L.doString("require 'lanes'.configure{with_timers = print}"), LuaError::OK); 597 L.requireFailure("require 'lanes'.configure{with_timers = 1}");
593} 598 }
594 599
595// ################################################################################################# 600 // -----------------------------------------------------------------------------------------
596 601
597TEST_F(Configure, WithTimersFalse) 602 SECTION("with_timers = <C function>")
598{ 603 {
599 EXPECT_EQ(L.doString("require 'lanes'.configure{with_timers = false}"), LuaError::OK); 604 L.requireFailure("require 'lanes'.configure{with_timers = print}");
600} 605 }
601 606
602// ################################################################################################# 607 // -----------------------------------------------------------------------------------------
603 608
604TEST_F(Configure, WithTimersTrue) 609 SECTION("with_timers = false")
605{ 610 {
606 EXPECT_EQ(L.doString("require 'lanes'.configure{with_timers = true}"), LuaError::OK); 611 L.requireSuccess("require 'lanes'.configure{with_timers = false}");
607} 612 }
608 613
609// ################################################################################################# 614 // -----------------------------------------------------------------------------------------
610// #################################################################################################
611// any unknown setting should be rejected
612 615
613TEST_F(Configure, UnknownSettingTable) 616 SECTION("with_timers = true")
614{ 617 {
615 EXPECT_NE(L.doString("require 'lanes'.configure{[{}] = {}}"), LuaError::OK); 618 L.requireSuccess("require 'lanes'.configure{with_timers = true}");
616} 619 }
620 }
617 621
618// ################################################################################################# 622 // ---------------------------------------------------------------------------------------------
623 // any unknown setting should be rejected
619 624
620TEST_F(Configure, UnknownSettingBool) 625 SECTION("unknown_setting")
621{ 626 {
622 EXPECT_NE(L.doString("require 'lanes'.configure{[true] = 'gluh'}"), LuaError::OK); 627 SECTION("table setting")
623} 628 {
629 L.requireFailure("require 'lanes'.configure{[{}] = {}}");
630 }
624 631
625// ################################################################################################# 632 // -----------------------------------------------------------------------------------------
626 633
627TEST_F(Configure, UnknownSettingFunction) 634 SECTION("boolean setting")
628{ 635 {
629 EXPECT_NE(L.doString("require 'lanes'.configure{[function() end] = 1}"), LuaError::OK); 636 L.requireFailure("require 'lanes'.configure{[true] = 'gluh'}");
630} 637 }
631 638
632// ################################################################################################# 639 // -----------------------------------------------------------------------------------------
633 640
634TEST_F(Configure, UnknownSettingNumber) 641 SECTION("function setting")
635{ 642 {
636 EXPECT_NE(L.doString("require 'lanes'.configure{[1] = function() end}"), LuaError::OK); 643 L.requireFailure("require 'lanes'.configure{[function() end] = 1}");
637} 644 }
638 645
639// ################################################################################################# 646 // -----------------------------------------------------------------------------------------
640 647
641TEST_F(Configure, UnknownSettingString) 648 SECTION("number setting")
642{ 649 {
643 EXPECT_NE(L.doString("require 'lanes'.configure{['gluh'] = false}"), LuaError::OK); 650 L.requireFailure("require 'lanes'.configure{[1] = function() end}");
651 }
652
653 // -----------------------------------------------------------------------------------------
654
655 SECTION("unknown string setting")
656 {
657 L.requireFailure("require 'lanes'.configure{['gluh'] = false}");
658 }
659 }
644} 660}
645 661
646// ################################################################################################# 662// #################################################################################################
647// ################################################################################################# 663// #################################################################################################
648 664
649TEST(Lanes, Finally) 665TEST_CASE("lanes.finally")
650{ 666{
667 SECTION("no fixture")
651 { 668 {
652 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; 669 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
653 // we need Lanes to be up. Since we run several 'scripts', we store it as a global 670 // we need Lanes to be up. Since we run several 'scripts', we store it as a global
654 EXPECT_EQ(S.doString("lanes = require 'lanes'"), LuaError::OK) << S; 671 S.requireSuccess("lanes = require 'lanes'");
655 // we can set a function 672 // we can set a function
656 EXPECT_EQ(S.doString("lanes.finally(function() end)"), LuaError::OK) << S; 673 S.requireSuccess("lanes.finally(function() end)");
657 // we can clear it 674 // we can clear it
658 EXPECT_EQ(S.doString("lanes.finally(nil)"), LuaError::OK) << S; 675 S.requireSuccess("lanes.finally(nil)");
659 // we can set a new one 676 // we can set a new one
660 EXPECT_EQ(S.doString("lanes.finally(function() end)"), LuaError::OK) << S; 677 S.requireSuccess("lanes.finally(function() end)");
661 // we can replace an existing function 678 // we can replace an existing function
662 EXPECT_EQ(S.doString("lanes.finally(error)"), LuaError::OK) << S; 679 S.requireSuccess("lanes.finally(error)");
663 // even if the finalizer throws a Lua error, it shouldn't crash anything 680 // even if the finalizer throws a Lua error, it shouldn't crash anything
664 ASSERT_NO_FATAL_FAILURE(S.close()); 681 REQUIRE_NOTHROW(S.close()); // TODO: use lua_atpanic to catch errors during close()
665 ASSERT_EQ(S.finalizerWasCalled, false); 682 REQUIRE_FALSE(S.finalizerWasCalled);
666 } 683 }
667 684
685 // ---------------------------------------------------------------------------------------------
686
687 SECTION("with fixture")
668 { 688 {
669 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; 689 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } };
670 690
671 // we need Lanes to be up. Since we run several 'scripts', we store it as a global 691 // we need Lanes to be up. Since we run several 'scripts', we store it as a global
672 EXPECT_EQ(S.doString("lanes = require 'lanes'"), LuaError::OK) << S; 692 S.requireSuccess("lanes = require 'lanes'");
673 // works because we have package.preload.fixture = luaopen_fixture 693 // works because we have package.preload.fixture = luaopen_fixture
674 EXPECT_EQ(S.doString("fixture = require 'fixture'"), LuaError::OK) << S; 694 S.requireSuccess("fixture = require 'fixture'");
675 // set our detectable finalizer 695 // set our detectable finalizer
676 EXPECT_EQ(S.doString("lanes.finally(fixture.throwing_finalizer)"), LuaError::OK) << S; 696 S.requireSuccess("lanes.finally(fixture.throwing_finalizer)");
677 // even if the finalizer can request a C++ exception, it shouldn't do it just now since we have no dangling lane 697 // even if the finalizer can request a C++ exception, it shouldn't do it just now since we have no dangling lane
678 ASSERT_NO_THROW(S.close()) << S; 698 REQUIRE_NOTHROW(S.close());
679 // the finalizer should be called 699 // the finalizer should be called
680 ASSERT_EQ(S.finalizerWasCalled, true); 700 REQUIRE(S.finalizerWasCalled);
681 } 701 }
682} 702}
683 703
@@ -697,97 +717,92 @@ namespace
697 } // namespace local 717 } // namespace local
698} 718}
699 719
700class OnStateCreate : public ::testing::Test
701{
702 protected:
703 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
704
705 void SetUp() override
706 {
707 local::OnStateCreateCallsCount.store(0, std::memory_order_relaxed);
708 }
709
710 void TearDown() override
711 {
712 local::OnStateCreateCallsCount.store(0, std::memory_order_relaxed);
713 }
714};
715
716// ################################################################################################# 720// #################################################################################################
717 721
718TEST_F(OnStateCreate, CalledInKeepers) 722TEST_CASE("on_state_create setting")
719{ 723{
720 // _G.on_state_create = on_state_create; 724 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
721 lua_pushcfunction(S, local::on_state_create);
722 lua_setglobal(S, "on_state_create");
723 ASSERT_EQ(S.doString("lanes = require 'lanes'.configure{on_state_create = on_state_create, nb_user_keepers = 3}"), LuaError::OK) << S;
724 ASSERT_EQ(local::OnStateCreateCallsCount.load(std::memory_order_relaxed), 4) << "on_state_create should have been called once in each Keeper state";
725}
726 725
727// ################################################################################################# 726 local::OnStateCreateCallsCount.store(0, std::memory_order_relaxed);
727 auto on_state_create = +[](lua_State* const L_) {
728 local::OnStateCreateCallsCount.fetch_add(1, std::memory_order_relaxed);
729 return 0;
730 };
728 731
729TEST_F(OnStateCreate, CalledInLane)
730{
731 // _G.on_state_create = on_state_create;
732 lua_pushcfunction(S, local::on_state_create);
733 lua_setglobal(S, "on_state_create");
734 ASSERT_EQ(S.doString("lanes = require 'lanes'.configure{on_state_create = on_state_create, with_timers = true}"), LuaError::OK) << S;
735 ASSERT_EQ(local::OnStateCreateCallsCount.load(std::memory_order_relaxed), 2) << "on_state_create should have been called in the Keeper state and the timer lane";
736}
737 732
738// ################################################################################################# 733 SECTION("on_state_create called in Keeper states")
734 {
735 // _G.on_state_create = on_state_create;
736 lua_pushcfunction(S, local::on_state_create);
737 lua_setglobal(S, "on_state_create");
738 S.requireSuccess("lanes = require 'lanes'.configure{on_state_create = on_state_create, nb_user_keepers = 3}");
739 REQUIRE(local::OnStateCreateCallsCount.load(std::memory_order_relaxed) == 4);
740 }
739 741
740TEST_F(OnStateCreate, CanPackagePreload) 742 // ---------------------------------------------------------------------------------------------
741{
742 // a C function for which we can test it was called
743 static bool _doStuffWasCalled{};
744 static auto _doStuff = +[](lua_State* const L_) {
745 _doStuffWasCalled = true;
746 return 0;
747 };
748 743
749 // a module that exports the above function 744 SECTION("on_state_create called in lane")
750 static auto _luaopen_Stuff = +[](lua_State* const L_) { 745 {
751 lua_newtable(L_); // t 746 // _G.on_state_create = on_state_create;
752 lua_pushstring(L_, "DoStuffInC"); // t "DoStuffInC" 747 lua_pushcfunction(S, local::on_state_create);
753 lua_pushcfunction(L_, _doStuff); // t "DoStuffInC" _doStuff 748 lua_setglobal(S, "on_state_create");
754 lua_settable(L_, -3); // t 749 S.requireSuccess("lanes = require 'lanes'.configure{on_state_create = on_state_create, with_timers = true}");
755 return 1; 750 REQUIRE(local::OnStateCreateCallsCount.load(std::memory_order_relaxed) == 2);
756 }; 751 }
757 752
758 // a function that installs the module loader function in package.preload 753 // ---------------------------------------------------------------------------------------------
759 auto _on_state_create = [](lua_State* const L_) {
760 754
761 lua_getglobal(L_, "package"); // package 755 SECTION("on_state_create changes package.preload")
762 if (lua_istable(L_, -1)) { 756 {
763 lua_getfield(L_, -1, "preload"); // package package.preload 757 // a C function for which we can test it was called
758 static bool _doStuffWasCalled{};
759 static auto _doStuff = +[](lua_State* const L_) {
760 _doStuffWasCalled = true;
761 return 0;
762 };
763
764 // a module that exports the above function
765 static auto _luaopen_Stuff = +[](lua_State* const L_) {
766 lua_newtable(L_); // t
767 lua_pushstring(L_, "DoStuffInC"); // t "DoStuffInC"
768 lua_pushcfunction(L_, _doStuff); // t "DoStuffInC" _doStuff
769 lua_settable(L_, -3); // t
770 return 1;
771 };
772
773 // a function that installs the module loader function in package.preload
774 auto _on_state_create = [](lua_State* const L_) {
775 lua_getglobal(L_, "package"); // package
764 if (lua_istable(L_, -1)) { 776 if (lua_istable(L_, -1)) {
765 lua_pushcfunction(L_, _luaopen_Stuff); // package package.preload luaopen_Stuff 777 lua_getfield(L_, -1, "preload"); // package package.preload
766 lua_setfield(L_, -2, "Stuff"); // package package.preload 778 if (lua_istable(L_, -1)) {
779 lua_pushcfunction(L_, _luaopen_Stuff); // package package.preload luaopen_Stuff
780 lua_setfield(L_, -2, "Stuff"); // package package.preload
781 }
782 lua_pop(L_, 1); // package
767 } 783 }
768 lua_pop(L_, 1); // package 784 lua_pop(L_, 1); //
769 }
770 lua_pop(L_, 1); //
771 785
772 return 0; 786 return 0;
773 }; 787 };
774 788
775 // _G.on_state_create = on_state_create; 789 // _G.on_state_create = on_state_create;
776 lua_pushcfunction(S, _on_state_create); 790 lua_pushcfunction(S, _on_state_create);
777 lua_setglobal(S, "on_state_create"); 791 lua_setglobal(S, "on_state_create");
778 792
779 ASSERT_EQ(S.doString("lanes = require 'lanes'.configure{on_state_create = on_state_create}"), LuaError::OK) << S; 793 S.requireSuccess("lanes = require 'lanes'.configure{on_state_create = on_state_create}");
780 794
781 // launch a Lane that requires the module. It should succeed because _on_state_create was called and made it possible 795 // launch a Lane that requires the module. It should succeed because _on_state_create was called and made it possible
782 std::string_view const _script{ 796 std::string_view const _script{
783 " f = lanes.gen('*'," 797 " f = lanes.gen('*',"
784 " function()" 798 " function()"
785 " local Stuff = require ('Stuff')" 799 " local Stuff = require ('Stuff')"
786 " Stuff.DoStuffInC()" 800 " Stuff.DoStuffInC()"
787 " return true" 801 " return true"
788 " end)" 802 " end)"
789 " f():join()" // start the lane and block until it terminates 803 " f():join()" // start the lane and block until it terminates
790 }; 804 };
791 ASSERT_EQ(S.doString(_script), LuaError::OK) << S; 805 S.requireSuccess(_script);
792 ASSERT_TRUE(_doStuffWasCalled); 806 REQUIRE(_doStuffWasCalled);
793} 807 }
808} \ No newline at end of file