1 #define SOL_CHECK_ARGUMENTS
2
3 #include <sol.hpp>
4 #include <catch.hpp>
5
6 #include <iostream>
7 #include <list>
8 #include <memory>
9 #include <mutex>
10
11 struct vars {
varsvars12 vars() {
13
14 }
15
16 int boop = 0;
17
~varsvars18 ~vars() {
19
20 }
21 };
22
23 struct fuser {
24 int x;
fuserfuser25 fuser() : x(0) {}
26
fuserfuser27 fuser(int x) : x(x) {}
28
addfuser29 int add(int y) {
30 return x + y;
31 }
32
add2fuser33 int add2(int y) {
34 return x + y + 2;
35 }
36 };
37
38 namespace crapola {
39 struct fuser {
40 int x;
fusercrapola::fuser41 fuser() : x(0) {}
fusercrapola::fuser42 fuser(int x) : x(x) {}
fusercrapola::fuser43 fuser(int x, int x2) : x(x * x2) {}
44
addcrapola::fuser45 int add(int y) {
46 return x + y;
47 }
add2crapola::fuser48 int add2(int y) {
49 return x + y + 2;
50 }
51 };
52 } // crapola
53
54 class Base {
55 public:
Base(int a_num)56 Base(int a_num) : m_num(a_num) { }
57
get_num()58 int get_num() {
59 return m_num;
60 }
61
62 protected:
63 int m_num;
64 };
65
66 class Derived : public Base {
67 public:
Derived(int a_num)68 Derived(int a_num) : Base(a_num) { }
69
get_num_10()70 int get_num_10() {
71 return 10 * m_num;
72 }
73 };
74
75 class abstract_A {
76 public:
77 virtual void a() = 0;
78 };
79
80 class abstract_B : public abstract_A {
81 public:
a()82 virtual void a() override {
83 INFO("overridden a() in B : public A - BARK");
84 }
85 };
86
87 struct Vec {
88 float x, y, z;
VecVec89 Vec(float x, float y, float z) : x{ x }, y{ y }, z{ z } {}
lengthVec90 float length() {
91 return sqrtf(x*x + y*y + z*z);
92 }
normalizedVec93 Vec normalized() {
94 float invS = 1 / length();
95 return{ x * invS, y * invS, z * invS };
96 }
97 };
98
99 struct giver {
100 int a = 0;
101
givergiver102 giver() {
103
104 }
105
giefgiver106 void gief() {
107 a = 1;
108 }
109
stuffgiver110 static void stuff() {
111
112 }
113
gief_stuffgiver114 static void gief_stuff(giver& t, int a) {
115 t.a = a;
116 }
117
~givergiver118 ~giver() {
119
120 }
121
122 };
123
124 struct factory_test {
125 private:
factory_testfactory_test126 factory_test() { a = true_a; }
~factory_testfactory_test127 ~factory_test() { a = 0; }
128 public:
129 static int num_saved;
130 static int num_killed;
131
132 struct deleter {
operator ()factory_test::deleter133 void operator()(factory_test* f) {
134 f->~factory_test();
135 }
136 };
137
138 static const int true_a;
139 int a;
140
makefactory_test141 static std::unique_ptr<factory_test, deleter> make() {
142 return std::unique_ptr<factory_test, deleter>(new factory_test(), deleter());
143 }
144
savefactory_test145 static void save(factory_test& f) {
146 new(&f)factory_test();
147 ++num_saved;
148 }
149
killfactory_test150 static void kill(factory_test& f) {
151 f.~factory_test();
152 ++num_killed;
153 }
154 };
155
156 int factory_test::num_saved = 0;
157 int factory_test::num_killed = 0;
158 const int factory_test::true_a = 156;
159
something()160 bool something() {
161 return true;
162 }
163
164 struct thing {
165 int v = 100;
166
thingthing167 thing() {}
thingthing168 thing(int x) : v(x) {}
169 };
170
171 struct self_test {
172 int bark;
173
self_testself_test174 self_test() : bark(100) {
175
176 }
177
gself_test178 void g(const std::string& str) {
179 std::cout << str << '\n';
180 bark += 1;
181 }
182
fself_test183 void f(const self_test& t) {
184 std::cout << "got test" << '\n';
185 if (t.bark != bark)
186 throw sol::error("bark values are not the same for self_test f function");
187 if (&t != this)
188 throw sol::error("call does not reference self for self_test f function");
189 }
190 };
191
192 struct ext_getset {
193
194 int bark = 24;
195 const int meow = 56;
196
197 ext_getset() = default;
ext_getsetext_getset198 ext_getset(int v) : bark(v) {}
199 ext_getset(ext_getset&&) = default;
200 ext_getset(const ext_getset&) = delete;
201 ext_getset& operator=(ext_getset&&) = default;
202 ext_getset& operator=(const ext_getset&) = delete;
~ext_getsetext_getset203 ~ext_getset() {
204
205 }
206
xext_getset207 std::string x() {
208 return "bark bark bark";
209 }
210
x2ext_getset211 int x2(std::string x) {
212 return static_cast<int>(x.length());
213 }
214
setext_getset215 void set(sol::variadic_args, sol::this_state, int x) {
216 bark = x;
217 }
218
getext_getset219 int get(sol::this_state, sol::variadic_args) {
220 return bark;
221 }
222
s_setext_getset223 static void s_set(int) {
224
225 }
226
s_getext_getset227 static int s_get(int x) {
228 return x + 20;
229 }
230
231 };
232
233 template <typename T>
des(T & e)234 void des(T& e) {
235 e.~T();
236 }
237
238 struct matrix_xf {
239 float a, b;
240
from_lua_tablematrix_xf241 static matrix_xf from_lua_table(sol::table t) {
242 matrix_xf m;
243 m.a = t[1][1];
244 m.b = t[1][2];
245 return m;
246 }
247 };
248
249 struct matrix_xi {
250 int a, b;
251
from_lua_tablematrix_xi252 static matrix_xi from_lua_table(sol::table t) {
253 matrix_xi m;
254 m.a = t[1][1];
255 m.b = t[1][2];
256 return m;
257 }
258 };
259
260 TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") {
261 sol::state lua;
262
263 sol::usertype<fuser> lc{ "add", &fuser::add, "add2", &fuser::add2 };
264 lua.set_usertype(lc);
265
266 lua.script("a = fuser:new()\n"
267 "b = a:add(1)\n"
268 "c = a:add2(1)\n");
269
270 sol::object a = lua.get<sol::object>("a");
271 sol::object b = lua.get<sol::object>("b");
272 sol::object c = lua.get<sol::object>("c");
273 REQUIRE((a.is<sol::userdata_value>()));
274 auto atype = a.get_type();
275 auto btype = b.get_type();
276 auto ctype = c.get_type();
277 REQUIRE((atype == sol::type::userdata));
278 REQUIRE((btype == sol::type::number));
279 REQUIRE((ctype == sol::type::number));
280 int bresult = b.as<int>();
281 int cresult = c.as<int>();
282 REQUIRE(bresult == 1);
283 REQUIRE(cresult == 3);
284 }
285
286 TEST_CASE("usertype/usertype-constructors", "Show that we can create classes from usertype and use them with multiple constructors") {
287
288 sol::state lua;
289
290 sol::constructors<sol::types<>, sol::types<int>, sol::types<int, int>> con;
291 sol::usertype<crapola::fuser> lc(con, "add", &crapola::fuser::add, "add2", &crapola::fuser::add2);
292 lua.set_usertype(lc);
293
294 lua.script(
295 "a = fuser.new(2)\n"
296 "u = a:add(1)\n"
297 "v = a:add2(1)\n"
298 "b = fuser:new()\n"
299 "w = b:add(1)\n"
300 "x = b:add2(1)\n"
301 "c = fuser.new(2, 3)\n"
302 "y = c:add(1)\n"
303 "z = c:add2(1)\n");
304 sol::object a = lua.get<sol::object>("a");
305 auto atype = a.get_type();
306 REQUIRE((atype == sol::type::userdata));
307 sol::object u = lua.get<sol::object>("u");
308 sol::object v = lua.get<sol::object>("v");
309 REQUIRE((u.as<int>() == 3));
310 REQUIRE((v.as<int>() == 5));
311
312 sol::object b = lua.get<sol::object>("b");
313 auto btype = b.get_type();
314 REQUIRE((btype == sol::type::userdata));
315 sol::object w = lua.get<sol::object>("w");
316 sol::object x = lua.get<sol::object>("x");
317 REQUIRE((w.as<int>() == 1));
318 REQUIRE((x.as<int>() == 3));
319
320 sol::object c = lua.get<sol::object>("c");
321 auto ctype = c.get_type();
322 REQUIRE((ctype == sol::type::userdata));
323 sol::object y = lua.get<sol::object>("y");
324 sol::object z = lua.get<sol::object>("z");
325 REQUIRE((y.as<int>() == 7));
326 REQUIRE((z.as<int>() == 9));
327 }
328
329 TEST_CASE("usertype/usertype-utility", "Show internal management of classes registered through new_usertype") {
330 sol::state lua;
331
332 lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
333
334 lua.script("a = fuser.new()\n"
335 "b = a:add(1)\n"
336 "c = a:add2(1)\n");
337
338 sol::object a = lua.get<sol::object>("a");
339 sol::object b = lua.get<sol::object>("b");
340 sol::object c = lua.get<sol::object>("c");
341 REQUIRE((a.is<sol::userdata_value>()));
342 auto atype = a.get_type();
343 auto btype = b.get_type();
344 auto ctype = c.get_type();
345 REQUIRE((atype == sol::type::userdata));
346 REQUIRE((btype == sol::type::number));
347 REQUIRE((ctype == sol::type::number));
348 int bresult = b.as<int>();
349 int cresult = c.as<int>();
350 REQUIRE(bresult == 1);
351 REQUIRE(cresult == 3);
352 }
353
354 TEST_CASE("usertype/usertype-utility-derived", "usertype classes must play nice when a derived class does not overload a publically visible base function") {
355 sol::state lua;
356 lua.open_libraries(sol::lib::base);
357 sol::constructors<sol::types<int>> basector;
358 sol::usertype<Base> baseusertype(basector, "get_num", &Base::get_num);
359
360 lua.set_usertype(baseusertype);
361
362 lua.script("base = Base.new(5)");
363 REQUIRE_NOTHROW(lua.script("print(base:get_num())"));
364
365 sol::constructors<sol::types<int>> derivedctor;
366 sol::usertype<Derived> derivedusertype(derivedctor,
367 "get_num_10", &Derived::get_num_10,
368 "get_num", &Derived::get_num
369 );
370
371 lua.set_usertype(derivedusertype);
372
373 lua.script("derived = Derived.new(7)");
374 lua.script("dgn = derived:get_num()\n"
375 "print(dgn)");
376 lua.script("dgn10 = derived:get_num_10()\n"
377 "print(dgn10)");
378
379 REQUIRE((lua.get<int>("dgn10") == 70));
380 REQUIRE((lua.get<int>("dgn") == 7));
381 }
382
383 TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice when C++ object types are requested for C++ code") {
384 sol::state lua;
385 lua.open_libraries(sol::lib::base);
386
387 lua.new_usertype<self_test>("test", "g", &self_test::g, "f", &self_test::f);
388
389 lua.script(
390 "local a = test.new()\n"
391 "a:g(\"woof\")\n"
392 "a:f(a)\n"
393 );
394 }
395
396 TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") {
397 struct test {
398 int x = 0;
settest399 test& set() {
400 x = 10;
401 return *this;
402 }
403
gettest404 int get() {
405 return x;
406 }
407
pgettest408 test* pget() {
409 return this;
410 }
411
create_gettest412 test create_get() {
413 return *this;
414 }
415
funtest416 int fun(int xa) {
417 return xa * 10;
418 }
419 };
420
421 sol::state lua;
422 lua.open_libraries(sol::lib::base);
423 lua.new_usertype<test>("test", "set", &test::set, "get", &test::get, "pointer_get", &test::pget, "fun", &test::fun, "create_get", &test::create_get);
424 REQUIRE_NOTHROW(lua.script("x = test.new()"));
425 REQUIRE_NOTHROW(lua.script("assert(x:set():get() == 10)"));
426 REQUIRE_NOTHROW(lua.script("y = x:pointer_get()"));
427 REQUIRE_NOTHROW(lua.script("y:set():get()"));
428 REQUIRE_NOTHROW(lua.script("y:fun(10)"));
429 REQUIRE_NOTHROW(lua.script("x:fun(10)"));
430 REQUIRE_NOTHROW(lua.script("assert(y:fun(10) == x:fun(10), '...')"));
431 REQUIRE_NOTHROW(lua.script("assert(y:fun(10) == 100, '...')"));
432 REQUIRE_NOTHROW(lua.script("assert(y:set():get() == y:set():get(), '...')"));
433 REQUIRE_NOTHROW(lua.script("assert(y:set():get() == 10, '...')"));
434 }
435
436 TEST_CASE("usertype/issue-number-thirty-five", "using value types created from lua-called C++ code, fixing user-defined types with constructors") {
437 sol::state lua;
438 lua.open_libraries(sol::lib::base);
439
440 sol::constructors<sol::types<float, float, float>> ctor;
441 sol::usertype<Vec> udata(ctor, "normalized", &Vec::normalized, "length", &Vec::length);
442 lua.set_usertype(udata);
443
444 REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n"
445 "print(v:length())"));
446 REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n"
447 "print(v:normalized():length())"));
448 }
449
450 TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored without keeping usertype object alive") {
451 sol::state lua;
452 lua.open_libraries(sol::lib::base);
453
454 {
455 sol::constructors<sol::types<float, float, float>> ctor;
456 sol::usertype<Vec> udata(ctor,
457 "normalized", &Vec::normalized,
458 "length", &Vec::length);
459
460 lua.set_usertype(udata);
461 // usertype dies, but still usable in lua!
462 }
463
464 REQUIRE_NOTHROW(lua.script("collectgarbage()\n"
465 "v = Vec.new(1, 2, 3)\n"
466 "print(v:length())"));
467
468 REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n"
469 "print(v:normalized():length())"));
470 }
471
472 TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as member variables for usertype") {
473 sol::state lua;
474 lua.open_libraries(sol::lib::base);
475 sol::constructors<sol::types<float, float, float>> ctor;
476 sol::usertype<Vec> udata(ctor,
477 "x", &Vec::x,
478 "y", &Vec::y,
479 "z", &Vec::z,
480 "normalized", &Vec::normalized,
481 "length", &Vec::length);
482 lua.set_usertype(udata);
483
484 REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n"
485 "v2 = Vec.new(0, 1, 0)\n"
486 "print(v:length())\n"
487 ));
488 REQUIRE_NOTHROW(lua.script("v.x = 2\n"
489 "v2.y = 2\n"
490 "print(v.x, v.y, v.z)\n"
491 "print(v2.x, v2.y, v2.z)\n"
492 ));
493 REQUIRE_NOTHROW(lua.script("assert(v.x == 2)\n"
494 "assert(v2.x == 0)\n"
495 "assert(v2.y == 2)\n"
496 ));
497 REQUIRE_NOTHROW(lua.script("v.x = 3\n"
498 "local x = v.x\n"
499 "assert(x == 3)\n"
500 ));
501
502 struct breaks {
503 sol::function f;
504 };
505
506 lua.open_libraries(sol::lib::base);
507 lua.set("b", breaks());
508 lua.new_usertype<breaks>("breaks",
509 "f", &breaks::f
510 );
511
512 breaks& b = lua["b"];
513 REQUIRE_NOTHROW(lua.script("b.f = function () print('BARK!') end"));
514 REQUIRE_NOTHROW(lua.script("b.f()"));
515 REQUIRE_NOTHROW(b.f());
516 }
517
518 TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") {
519 sol::state lua;
520 lua.open_libraries(sol::lib::base);
521
522 lua.new_usertype<giver>("giver",
523 "gief_stuff", giver::gief_stuff,
524 "gief", &giver::gief,
__anonb28a877d0102(const giver& t) 525 "__tostring", [](const giver& t) {
526 return std::to_string(t.a) + ": giving value";
527 }
528 ).get<sol::table>("giver")
529 .set_function("stuff", giver::stuff);
530
531 REQUIRE_NOTHROW(lua.script("giver.stuff()"));
532 REQUIRE_NOTHROW(lua.script("t = giver.new()\n"
533 "print(tostring(t))\n"
534 "t:gief()\n"
535 "t:gief_stuff(20)\n"));
536 giver& g = lua.get<giver>("t");
537 REQUIRE(g.a == 20);
538 }
539
540 TEST_CASE("usertype/unique-shared-ptr", "manage the conversion and use of unique and shared pointers ('unique usertypes')") {
541 const int64_t unique_value = 0x7125679355635963;
542 auto uniqueint = std::make_unique<int64_t>(unique_value);
543 auto sharedint = std::make_shared<int64_t>(unique_value);
544 long preusecount = sharedint.use_count();
545 { sol::state lua;
546 lua.open_libraries(sol::lib::base);
547 lua.set("uniqueint", std::move(uniqueint));
548 lua.set("sharedint", sharedint);
549 std::unique_ptr<int64_t>& uniqueintref = lua["uniqueint"];
550 std::shared_ptr<int64_t>& sharedintref = lua["sharedint"];
551 int64_t* rawuniqueintref = lua["uniqueint"];
552 int64_t* rawsharedintref = lua["sharedint"];
553 int siusecount = sharedintref.use_count();
554 REQUIRE((uniqueintref.get() == rawuniqueintref && sharedintref.get() == rawsharedintref));
555 REQUIRE((uniqueintref != nullptr && sharedintref != nullptr && rawuniqueintref != nullptr && rawsharedintref != nullptr));
556 REQUIRE((unique_value == *uniqueintref.get() && unique_value == *sharedintref.get()));
557 REQUIRE((unique_value == *rawuniqueintref && unique_value == *rawsharedintref));
558 REQUIRE(siusecount == sharedint.use_count());
559 std::shared_ptr<int64_t> moreref = sharedint;
560 REQUIRE(unique_value == *moreref.get());
561 REQUIRE(moreref.use_count() == sharedint.use_count());
562 REQUIRE(moreref.use_count() == sharedintref.use_count());
563 }
564 REQUIRE(preusecount == sharedint.use_count());
565 }
566
567 TEST_CASE("regressions/one", "issue number 48") {
568 sol::state lua;
569 lua.new_usertype<vars>("vars",
570 "boop", &vars::boop);
571 REQUIRE_NOTHROW(lua.script("beep = vars.new()\n"
572 "beep.boop = 1"));
573 // test for segfault
574 auto my_var = lua.get<vars>("beep");
575 REQUIRE(my_var.boop == 1);
576 auto* ptr = &my_var;
577 REQUIRE(ptr->boop == 1);
578 }
579
580 TEST_CASE("usertype/get-set-references", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified<T> on the type...") {
581 sol::state lua;
582
583 lua.new_usertype<vars>("vars",
584 "boop", &vars::boop);
585 vars var{};
586 vars rvar{};
587 lua.set("beep", var);
588 lua.set("rbeep", std::ref(rvar));
589 auto& my_var = lua.get<vars>("beep");
590 auto& ref_var = lua.get<std::reference_wrapper<vars>>("rbeep");
591 vars& proxy_my_var = lua["beep"];
592 std::reference_wrapper<vars> proxy_ref_var = lua["rbeep"];
593 var.boop = 2;
594 rvar.boop = 5;
595
596 // Was return as a value: var must be diferent from "beep"
597 REQUIRE_FALSE(std::addressof(var) == std::addressof(my_var));
598 REQUIRE_FALSE(std::addressof(proxy_my_var) == std::addressof(var));
599 REQUIRE((my_var.boop == 0));
600 REQUIRE(var.boop != my_var.boop);
601
602 REQUIRE(std::addressof(ref_var) == std::addressof(rvar));
603 REQUIRE(std::addressof(proxy_ref_var.get()) == std::addressof(rvar));
604 REQUIRE(rvar.boop == 5);
605 REQUIRE(rvar.boop == ref_var.boop);
606 }
607
608 TEST_CASE("usertype/destructor-tests", "Show that proper copies / destruction happens") {
609 static int created = 0;
610 static int destroyed = 0;
611 static void* last_call = nullptr;
612 struct x {
xx613 x() { ++created; }
xx614 x(const x&) { ++created; }
xx615 x(x&&) { ++created; }
operator =x616 x& operator=(const x&) { return *this; }
operator =x617 x& operator=(x&&) { return *this; }
~xx618 ~x() { ++destroyed; }
619 };
620 {
621 sol::state lua;
622 lua.new_usertype<x>("x");
623 x x1;
624 x x2;
625 lua.set("x1copy", x1, "x2copy", x2, "x1ref", std::ref(x1));
626 x& x1copyref = lua["x1copy"];
627 x& x2copyref = lua["x2copy"];
628 x& x1ref = lua["x1ref"];
629 REQUIRE(created == 4);
630 REQUIRE(destroyed == 0);
631 REQUIRE(std::addressof(x1) == std::addressof(x1ref));
632 REQUIRE(std::addressof(x1copyref) != std::addressof(x1));
633 REQUIRE(std::addressof(x2copyref) != std::addressof(x2));
634 }
635 REQUIRE(created == 4);
636 REQUIRE(destroyed == 4);
637 }
638
639 TEST_CASE("usertype/private-constructible", "Check to make sure special snowflake types from Enterprise thingamahjongs work properly.") {
640 int numsaved = factory_test::num_saved;
641 int numkilled = factory_test::num_killed;
642 {
643 sol::state lua;
644 lua.open_libraries(sol::lib::base);
645
646 lua.new_usertype<factory_test>("factory_test",
647 "new", sol::initializers(factory_test::save),
648 "__gc", sol::destructor(factory_test::kill),
649 "a", &factory_test::a
650 );
651
652 std::unique_ptr<factory_test, factory_test::deleter> f = factory_test::make();
653 lua.set("true_a", factory_test::true_a, "f", f.get());
654 REQUIRE_NOTHROW(lua.script("assert(f.a == true_a)"));
655
656 REQUIRE_NOTHROW(lua.script(
657 "local fresh_f = factory_test:new()\n"
658 "assert(fresh_f.a == true_a)\n"));
659 }
660 int expectednumsaved = numsaved + 1;
661 int expectednumkilled = numkilled + 1;
662 REQUIRE(expectednumsaved == factory_test::num_saved);
663 REQUIRE(expectednumkilled == factory_test::num_killed);
664 }
665
666 TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") {
667 struct A { int x = 201; };
668 struct B {
fooB669 int foo(const A* a) { return a->x; };
670 };
671
672 sol::state lua;
673 lua.new_usertype<B>("B",
674 "foo", &B::foo
675 );
676 lua.set("a", A());
677 lua.set("b", B());
678 lua.script("x = b:foo(a)");
679 int x = lua["x"];
680 REQUIRE(x == 201);
681 }
682
683 TEST_CASE("usertype/overloading", "Check if overloading works properly for usertypes") {
684 struct woof {
685 int var;
686
funcwoof687 int func(int x) {
688 return var + x;
689 }
690
func2woof691 double func2(int x, int y) {
692 return var + x + y + 0.5;
693 }
694
func2swoof695 std::string func2s(int x, std::string y) {
696 return y + " " + std::to_string(x);
697 }
698 };
699 sol::state lua;
700 lua.open_libraries(sol::lib::base);
701
702 lua.new_usertype<woof>("woof",
703 "var", &woof::var,
704 "func", sol::overload(&woof::func, &woof::func2, &woof::func2s)
705 );
706
707 const std::string bark_58 = "bark 58";
708
709 REQUIRE_NOTHROW(lua.script(
710 "r = woof:new()\n"
711 "a = r:func(1)\n"
712 "b = r:func(1, 2)\n"
713 "c = r:func(58, 'bark')\n"
714 ));
715 REQUIRE((lua["a"] == 1));
716 REQUIRE((lua["b"] == 3.5));
717 REQUIRE((lua["c"] == bark_58));
718
719 REQUIRE_THROWS(lua.script("r:func(1,2,'meow')"));
720 }
721
722 TEST_CASE("usertype/overloading_values", "ensure overloads handle properly") {
723 struct overloading_test {
printoverloading_test724 int print(int i) { INFO("Integer print: " << i); return 500 + i; }
printoverloading_test725 int print() { INFO("No param print."); return 500; }
726 };
727
728 sol::state lua;
729 lua.new_usertype<overloading_test>("overloading_test", sol::constructors<>(),
730 "print", sol::overload(static_cast<int (overloading_test::*)(int)>(&overloading_test::print), static_cast<int (overloading_test::*)()>(&overloading_test::print)),
731 "print2", sol::overload(static_cast<int (overloading_test::*)()>(&overloading_test::print), static_cast<int (overloading_test::*)(int)>(&overloading_test::print))
732 );
733 lua.set("test", overloading_test());
734
735 sol::function f0_0 = lua.load("return test:print()");
736 sol::function f0_1 = lua.load("return test:print2()");
737 sol::function f1_0 = lua.load("return test:print(24)");
738 sol::function f1_1 = lua.load("return test:print2(24)");
739 int res = f0_0();
740 int res2 = f0_1();
741 int res3 = f1_0();
742 int res4 = f1_1();
743
744 REQUIRE(res == 500);
745 REQUIRE(res2 == 500);
746
747 REQUIRE(res3 == 524);
748 REQUIRE(res4 == 524);
749 }
750
751 TEST_CASE("usertype/reference-and-constness", "Make sure constness compiles properly and errors out at runtime") {
752 struct bark {
753 int var = 50;
754 };
755 struct woof {
756 bark b;
757 };
758
759 struct nested {
760 const int f = 25;
761 };
762
763 struct outer {
764 nested n;
765 };
766
767 sol::state lua;
768 lua.new_usertype<woof>("woof",
769 "b", &woof::b);
770 lua.new_usertype<bark>("bark",
771 "var", &bark::var);
772 lua.new_usertype<outer>("outer",
773 "n", &outer::n);
774 lua.set("w", woof());
775 lua.set("n", nested());
776 lua.set("o", outer());
777 lua.set("f", sol::c_call<decltype(&nested::f), &nested::f>);
778 lua.script(R"(
779 x = w.b
780 x.var = 20
781 val = w.b.var == x.var
782 v = f(n);
783 )");
784
785 woof& w = lua["w"];
786 bark& x = lua["x"];
787 nested& n = lua["n"];
788 int v = lua["v"];
789 bool val = lua["val"];
790 // enforce reference semantics
791 REQUIRE(std::addressof(w.b) == std::addressof(x));
792 REQUIRE(n.f == 25);
793 REQUIRE(v == 25);
794 REQUIRE(val);
795
796 REQUIRE_THROWS(lua.script("f(n, 50)"));
797 REQUIRE_THROWS(lua.script("o.n = 25"));
798 }
799
800 TEST_CASE("usertype/readonly-and-static-functions", "Check if static functions can be called on userdata and from their originating (meta)tables") {
801 struct bark {
802 int var = 50;
803
funcbark804 void func() {}
805
oh_boybark806 static void oh_boy() {}
807
oh_boybark808 static int oh_boy(std::string name) {
809 return static_cast<int>(name.length());
810 }
811
operator ()bark812 int operator()(int x) {
813 return x;
814 }
815 };
816
817 sol::state lua;
818 lua.open_libraries(sol::lib::base);
819 lua.new_usertype<bark>("bark",
820 "var", &bark::var,
821 "var2", sol::readonly(&bark::var),
822 "something", something,
__anonb28a877d0202(int x, int y) 823 "something2", [](int x, int y) { return x + y; },
824 "func", &bark::func,
825 "oh_boy", sol::overload(sol::resolve<void()>(&bark::oh_boy), sol::resolve<int(std::string)>(&bark::oh_boy)),
826 sol::meta_function::call_function, &bark::operator()
827 );
828
829 REQUIRE_NOTHROW(lua.script("assert(bark.oh_boy('woo') == 3)"));
830 REQUIRE_NOTHROW(lua.script("bark.oh_boy()"));
831
832 bark b;
833 lua.set("b", &b);
834
835 sol::table b_table = lua["b"];
836 sol::function member_func = b_table["func"];
837 sol::function s = b_table["something"];
838 sol::function s2 = b_table["something2"];
839
840 sol::table b_metatable = b_table[sol::metatable_key];
841 bool isvalidmt = b_metatable.valid();
842 REQUIRE(isvalidmt);
843 sol::function b_call = b_metatable["__call"];
844 sol::function b_as_function = lua["b"];
845
846 int x = b_as_function(1);
847 int y = b_call(b, 1);
848 bool z = s();
849 int w = s2(2, 3);
850 REQUIRE(x == 1);
851 REQUIRE(y == 1);
852 REQUIRE(z);
853 REQUIRE(w == 5);
854
855 lua.script(R"(
856 lx = b(1)
857 ly = getmetatable(b).__call(b, 1)
858 lz = b.something()
859 lz2 = bark.something()
860 lw = b.something2(2, 3)
861 lw2 = bark.something2(2, 3)
862 )");
863
864 int lx = lua["lx"];
865 int ly = lua["ly"];
866 bool lz = lua["lz"];
867 int lw = lua["lw"];
868 bool lz2 = lua["lz2"];
869 int lw2 = lua["lw2"];
870 REQUIRE(lx == 1);
871 REQUIRE(ly == 1);
872 REQUIRE(lz);
873 REQUIRE(lz2);
874 REQUIRE(lw == 5);
875 REQUIRE(lw2 == 5);
876 REQUIRE(lx == ly);
877 REQUIRE(lz == lz2);
878 REQUIRE(lw == lw2);
879
880 REQUIRE_THROWS(lua.script("b.var2 = 2"));
881 }
882
883 TEST_CASE("usertype/properties", "Check if member properties/variables work") {
884 struct bark {
885 int var = 50;
886 int var2 = 25;
887
get_var2bark888 int get_var2() const {
889 return var2;
890 }
891
get_var3bark892 int get_var3() {
893 return var2;
894 }
895
set_var2bark896 void set_var2(int x) {
897 var2 = x;
898 }
899 };
900
901 sol::state lua;
902 lua.open_libraries(sol::lib::base);
903 lua.new_usertype<bark>("bark",
904 "var", &bark::var,
905 "var2", sol::readonly(&bark::var2),
906 "a", sol::property(&bark::get_var2, &bark::set_var2),
907 "b", sol::property(&bark::get_var2),
908 "c", sol::property(&bark::get_var3),
909 "d", sol::property(&bark::set_var2)
910 );
911
912 bark b;
913 lua.set("b", &b);
914
915 lua.script("b.a = 59");
916 lua.script("var2_0 = b.a");
917 lua.script("var2_1 = b.b");
918 lua.script("b.d = 1568");
919 lua.script("var2_2 = b.c");
920
921 int var2_0 = lua["var2_0"];
922 int var2_1 = lua["var2_1"];
923 int var2_2 = lua["var2_2"];
924 REQUIRE(var2_0 == 59);
925 REQUIRE(var2_1 == 59);
926 REQUIRE(var2_2 == 1568);
927
928 REQUIRE_THROWS(lua.script("b.var2 = 24"));
929 REQUIRE_THROWS(lua.script("r = b.d"));
930 REQUIRE_THROWS(lua.script("r = b.d"));
931 REQUIRE_THROWS(lua.script("b.b = 25"));
932 REQUIRE_THROWS(lua.script("b.c = 11"));
933 }
934
935 TEST_CASE("usertype/safety", "crash with an exception -- not a segfault -- on bad userdata calls") {
936 class Test {
937 public:
sayHello()938 void sayHello() { std::cout << "Hey\n"; }
939 };
940
941 sol::state lua;
942 lua.new_usertype<Test>("Test", "sayHello", &Test::sayHello);
943 static const std::string code = R"(
944 local t = Test.new()
945 t:sayHello() --Works fine
946 t.sayHello() --Uh oh.
947 )";
948 REQUIRE_THROWS(lua.script(code));
949 }
950
951 TEST_CASE("usertype/call_constructor", "make sure lua types can be constructed with function call constructors") {
952 sol::state lua;
953 lua.open_libraries(sol::lib::base);
954
955 lua.new_usertype<thing>("thing",
956 "v", &thing::v
957 , sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>()
958 );
959
960 lua.script(R"(
961 t = thing(256)
962 )");
963
964 thing& y = lua["t"];
965 INFO(y.v);
966 REQUIRE(y.v == 256);
967 }
968
969 TEST_CASE("usertype/call_constructor-factories", "make sure tables can be passed to factory-based call constructors") {
970 sol::state lua;
971 lua.open_libraries();
972
973 lua.new_usertype<matrix_xf>("mat",
974 sol::call_constructor, sol::factories(&matrix_xf::from_lua_table)
975 );
976
977 lua.script("m = mat{ {1.1, 2.2} }");
978
979 lua.new_usertype<matrix_xi>("mati",
980 sol::call_constructor, sol::factories(&matrix_xi::from_lua_table)
981 );
982
983 lua.script("mi = mati{ {1, 2} }");
984
985 matrix_xf& m = lua["m"];
986 REQUIRE(m.a == 1.1f);
987 REQUIRE(m.b == 2.2f);
988 matrix_xi& mi = lua["mi"];
989 REQUIRE(mi.a == 1);
990 REQUIRE(mi.b == 2);
991 }
992
993 TEST_CASE("usertype/call_constructor_2", "prevent metatable regression") {
994 class class01 {
995 public:
996 int x = 57;
class01()997 class01() {}
998 };
999
1000 class class02 {
1001 public:
1002 int x = 50;
class02()1003 class02() {}
class02(const class01 & other)1004 class02(const class01& other) : x(other.x) {}
1005 };
1006
1007 sol::state lua;
1008
1009 lua.new_usertype<class01>("class01",
1010 sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class01&>>()
1011 );
1012
1013 lua.new_usertype<class02>("class02",
1014 sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class02&>, sol::types<const class01&>>()
1015 );
1016
1017 REQUIRE_NOTHROW(lua.script(R"(
1018 x = class01()
1019 y = class02(x)
1020 )"));
1021 class02& y = lua["y"];
1022 REQUIRE(y.x == 57);
1023 }
1024
1025 TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
1026 sol::state lua;
1027 lua.open_libraries(sol::lib::base);
1028
1029 lua.new_usertype<thing>("thing",
1030 "v", &thing::v
1031 , sol::call_constructor, sol::constructors<>()
1032 );
1033
1034 REQUIRE_THROWS(lua.script("t = thing(256)"));
1035 }
1036
1037
1038 TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
1039 sol::state lua;
1040 lua.open_libraries(sol::lib::base);
1041
1042 SECTION("order1")
1043 {
1044 lua.new_usertype<thing>("thing",
1045 "v", &thing::v
1046 , sol::call_constructor, sol::no_constructor
1047 );
1048 REQUIRE_THROWS(lua.script("t = thing.new()"));
1049 }
1050
1051 SECTION("order2")
1052 {
1053 lua.new_usertype<thing>("thing"
1054 , sol::call_constructor, sol::no_constructor
1055 , "v", &thing::v
1056 );
1057 REQUIRE_THROWS(lua.script("t = thing.new()"));
1058 }
1059
1060 REQUIRE_THROWS(lua.script("t = thing.new()"));
1061 }
1062
1063 TEST_CASE("usertype/coverage", "try all the things") {
1064 sol::state lua;
1065 lua.open_libraries(sol::lib::base);
1066
1067 lua.new_usertype<ext_getset>("ext_getset",
1068 sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>(),
1069 sol::meta_function::garbage_collect, sol::destructor(des<ext_getset>),
__anonb28a877d0302(ext_getset& m, std::string x, int y) 1070 "x", sol::overload(&ext_getset::x, &ext_getset::x2, [](ext_getset& m, std::string x, int y) {
1071 return m.meow + 50 + y + x.length();
1072 }),
1073 "bark", &ext_getset::bark,
1074 "meow", &ext_getset::meow,
1075 "readonlybark", sol::readonly(&ext_getset::bark),
1076 "set", &ext_getset::set,
1077 "get", &ext_getset::get,
1078 "sset", &ext_getset::s_set,
1079 "sget", &ext_getset::s_get,
1080 "propbark", sol::property(&ext_getset::set, &ext_getset::get),
1081 "readonlypropbark", sol::property(&ext_getset::get),
1082 "writeonlypropbark", sol::property(&ext_getset::set)
1083 );
1084
1085 INFO("usertype created");
1086
1087 lua.script(R"(
1088 e = ext_getset()
1089 w = e:x(e:x(), e:x(e:x()))
1090 print(w)
1091 )");
1092
1093 int w = lua["w"];
1094 REQUIRE(w == (56 + 50 + 14 + 14));
1095
1096 INFO("REQUIRE(w) successful");
1097
1098 lua.script(R"(
1099 e:set(500)
1100 e.sset(24)
1101 x = e:get()
1102 y = e.sget(20)
1103 )");
1104
1105 int x = lua["x"];
1106 int y = lua["y"];
1107 REQUIRE(x == 500);
1108 REQUIRE(y == 40);
1109
1110 INFO("REQUIRE(x, y) successful");
1111
1112 lua.script(R"(
1113 e.bark = 5001
1114 a = e:get()
1115 print(e.bark)
1116 print(a)
1117
1118 e.propbark = 9700
1119 b = e:get()
1120 print(e.propbark)
1121 print(b)
1122 )");
1123 int a = lua["a"];
1124 int b = lua["b"];
1125
1126 REQUIRE(a == 5001);
1127 REQUIRE(b == 9700);
1128
1129 INFO("REQUIRE(a, b) successful");
1130
1131 lua.script(R"(
1132 c = e.readonlybark
1133 d = e.meow
1134 print(e.readonlybark)
1135 print(c)
1136 print(e.meow)
1137 print(d)
1138 )");
1139
1140 int c = lua["c"];
1141 int d = lua["d"];
1142 REQUIRE(c == 9700);
1143 REQUIRE(d == 56);
1144
1145 INFO("REQUIRE(c, d) successful");
1146
1147 lua.script(R"(
1148 e.writeonlypropbark = 500
1149 z = e.readonlypropbark
1150 print(e.readonlybark)
1151 print(e.bark)
1152 )");
1153
1154 int z = lua["z"];
1155 REQUIRE(z == 500);
1156
1157 INFO("REQUIRE(z) successful");
1158
1159 REQUIRE_THROWS(lua.script("e.readonlybark = 24"));
1160 INFO("REQUIRE_THROWS 1 successful");
1161 REQUIRE_THROWS(lua.script("e.readonlypropbark = 500"));
1162 INFO("REQUIRE_THROWS 2 successful");
1163 REQUIRE_THROWS(lua.script("y = e.writeonlypropbark"));
1164 INFO("REQUIRE_THROWS 3 successful");
1165
1166 }
1167
1168 TEST_CASE("usertype/copyability", "make sure user can write to a class variable even if the class itself isn't copy-safe") {
1169 struct NoCopy {
getNoCopy1170 int get() const { return _you_can_copy_me; }
setNoCopy1171 void set(int val) { _you_can_copy_me = val; }
1172
1173 int _you_can_copy_me;
1174 std::mutex _haha_you_cant_copy_me;
1175 };
1176
1177 sol::state lua;
1178 lua.new_usertype<NoCopy>("NoCopy", "val", sol::property(&NoCopy::get, &NoCopy::set));
1179
1180 REQUIRE_NOTHROW(
1181 lua.script(R"__(
1182 nocopy = NoCopy.new()
1183 nocopy.val = 5
1184 )__")
1185 );
1186 }
1187
1188 TEST_CASE("usertype/protect", "users should be allowed to manually protect a function") {
1189 struct protect_me {
genprotect_me1190 int gen(int x) {
1191 return x;
1192 }
1193 };
1194
1195 sol::state lua;
1196 lua.open_libraries(sol::lib::base);
1197 lua.new_usertype<protect_me>("protect_me",
1198 "gen", sol::protect( &protect_me::gen )
1199 );
1200
1201 REQUIRE_NOTHROW(
1202 lua.script(R"__(
1203 pm = protect_me.new()
1204 value = pcall(pm.gen,pm)
1205 )__");
1206 );
1207 bool value = lua["value"];
1208 REQUIRE_FALSE(value);
1209 }
1210
1211 TEST_CASE("usertype/shared-ptr-regression", "usertype metatables should not screw over unique usertype metatables") {
1212 static int created = 0;
1213 static int destroyed = 0;
1214 struct test {
testtest1215 test() {
1216 ++created;
1217 }
1218
~testtest1219 ~test() {
1220 ++destroyed;
1221 }
1222 };
1223 {
1224 std::list<std::shared_ptr<test>> tests;
1225 sol::state lua;
1226 lua.open_libraries();
1227
1228 lua.new_usertype<test>("test",
__anonb28a877d0402() 1229 "create", [&]() -> std::shared_ptr<test> {
1230 tests.push_back(std::make_shared<test>());
1231 return tests.back();
1232 }
1233 );
1234 REQUIRE(created == 0);
1235 REQUIRE(destroyed == 0);
1236 lua.script("x = test.create()");
1237 REQUIRE(created == 1);
1238 REQUIRE(destroyed == 0);
1239 REQUIRE_FALSE(tests.empty());
1240 std::shared_ptr<test>& x = lua["x"];
1241 std::size_t xuse = x.use_count();
1242 std::size_t tuse = tests.back().use_count();
1243 REQUIRE(xuse == tuse);
1244 }
1245 REQUIRE(created == 1);
1246 REQUIRE(destroyed == 1);
1247 }
1248
1249 TEST_CASE("usertype/double-deleter-guards", "usertype metatables internally must not rely on internal ") {
1250 struct c_a { int x; };
1251 struct c_b { int y; };
1252 REQUIRE_NOTHROW( {
1253 sol::state lua;
1254 lua.new_usertype<c_a>("c_a", "x", &c_a::x);
1255 lua.new_usertype<c_b>("c_b", "y", &c_b::y);
1256 lua = sol::state();
1257 lua.new_usertype<c_a>("c_a", "x", &c_a::x);
1258 lua.new_usertype<c_b>("c_b", "y", &c_b::y);
1259 lua = sol::state();
1260 });
1261 }
1262
1263 TEST_CASE("usertype/vars", "usertype vars can bind various class items") {
1264 static int muh_variable = 25;
1265 static int through_variable = 10;
1266
1267 sol::state lua;
1268 lua.open_libraries();
1269 struct test {};
1270 lua.new_usertype<test>("test",
1271 "straight", sol::var(2),
1272 "global", sol::var(muh_variable),
1273 "ref_global", sol::var(std::ref(muh_variable)),
1274 "global2", sol::var(through_variable),
1275 "ref_global2", sol::var(std::ref(through_variable))
1276 );
1277
1278 int prets = lua["test"]["straight"];
1279 int pretg = lua["test"]["global"];
1280 int pretrg = lua["test"]["ref_global"];
1281 int pretg2 = lua["test"]["global2"];
1282 int pretrg2 = lua["test"]["ref_global2"];
1283
1284 REQUIRE(prets == 2);
1285 REQUIRE(pretg == 25);
1286 REQUIRE(pretrg == 25);
1287 REQUIRE(pretg2 == 10);
1288 REQUIRE(pretrg2 == 10);
1289
1290 lua.script(R"(
1291 print(test.straight)
1292 test.straight = 50
1293 print(test.straight)
1294 )");
1295 int s = lua["test"]["straight"];
1296 REQUIRE(s == 50);
1297
1298 lua.script(R"(
1299 t = test.new()
1300 print(t.global)
1301 t.global = 50
1302 print(t.global)
1303 )");
1304 int mv = lua["test"]["global"];
1305 REQUIRE(mv == 50);
1306 REQUIRE(muh_variable == 25);
1307
1308
1309 lua.script(R"(
1310 print(t.ref_global)
1311 t.ref_global = 50
1312 print(t.ref_global)
1313 )");
1314 int rmv = lua["test"]["ref_global"];
1315 REQUIRE(rmv == 50);
1316 REQUIRE(muh_variable == 50);
1317
1318 REQUIRE(through_variable == 10);
1319 lua.script(R"(
1320 print(test.global2)
1321 test.global2 = 35
1322 print(test.global2)
1323 )");
1324 int tv = lua["test"]["global2"];
1325 REQUIRE(through_variable == 10);
1326 REQUIRE(tv == 35);
1327
1328 lua.script(R"(
1329 print(test.ref_global2)
1330 test.ref_global2 = 35
1331 print(test.ref_global2)
1332 )");
1333 int rtv = lua["test"]["ref_global2"];
1334 REQUIRE(rtv == 35);
1335 REQUIRE(through_variable == 35);
1336 }
1337
1338 TEST_CASE("usertypes/var-and-property", "make sure const vars are readonly and properties can handle lambdas") {
1339 const static int arf = 20;
1340
1341 struct test {
1342 int value = 10;
1343 };
1344
1345 sol::state lua;
1346 lua.open_libraries();
1347
1348 lua.new_usertype<test>("test",
1349 "prop", sol::property(
__anonb28a877d0502(test& t) 1350 [](test& t) {
1351 return t.value;
1352 },
__anonb28a877d0602(test& t, int x) 1353 [](test& t, int x) {
1354 t.value = x;
1355 }
1356 ),
1357 "global", sol::var(std::ref(arf))
1358 );
1359
1360 lua.script(R"(
1361 t = test.new()
1362 print(t.prop)
1363 t.prop = 50
1364 print(t.prop)
1365 )");
1366
1367 test& t = lua["t"];
1368 REQUIRE(t.value == 50);
1369
1370
1371 REQUIRE_THROWS(
1372 lua.script(R"(
1373 t = test.new()
1374 print(t.global)
1375 t.global = 20
1376 print(t.global)
1377 )"));
1378 }
1379
1380 TEST_CASE("usertype/unique_usertype-check", "make sure unique usertypes don't get pushed as references with function calls and the like") {
1381 class Entity {
1382 public:
GetName()1383 std::string GetName() {
1384 return "Charmander";
1385 }
1386 };
1387
1388 sol::state lua;
1389 lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string, sol::lib::io);
1390
1391 lua.new_usertype<Entity>("Entity",
1392 "new", sol::no_constructor,
1393 "get_name", &Entity::GetName
1394 );
1395
1396 lua.script(R"(
1397 function my_func(entity)
1398 print("INSIDE LUA")
1399 print(entity:get_name())
1400 end
1401 )");
1402
1403 sol::function my_func = lua["my_func"];
1404 REQUIRE_NOTHROW({
1405 auto ent = std::make_shared<Entity>();
1406 my_func(ent);
1407 Entity ent2;
1408 my_func(ent2);
1409 my_func(std::make_shared<Entity>());
1410 });
1411 }
1412
1413 TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") {
1414 sol::state lua;
1415 lua.new_usertype<abstract_A>("A", "a", &abstract_A::a);
1416 lua.new_usertype<abstract_B>("B", sol::base_classes, sol::bases<abstract_A>());
1417 lua.script(R"(local b = B.new()
1418 b:a()
1419 )");
1420 }
1421
1422 TEST_CASE("usertype/as_function", "Ensure that variables can be turned into functions by as_function") {
1423 class B {
1424 public:
1425 int bvar = 24;
1426 };
1427
1428 sol::state lua;
1429 lua.open_libraries();
1430 lua.new_usertype<B>("B", "b", &B::bvar, "f", sol::as_function(&B::bvar));
1431
1432 B b;
1433 lua.set("b", &b);
1434 lua.script("x = b:f()");
1435 lua.script("y = b.b");
1436 int x = lua["x"];
1437 int y = lua["y"];
1438 REQUIRE(x == 24);
1439 REQUIRE(y == 24);
1440 }
1441
1442 TEST_CASE("usertype/destruction-test", "make sure usertypes are properly destructed and don't double-delete memory or segfault") {
1443 sol::state lua;
1444
1445 class CrashClass {
1446 public:
CrashClass()1447 CrashClass() {
1448 }
1449
~CrashClass()1450 ~CrashClass() {
1451 a = 10; // This will cause a crash.
1452 }
1453
1454 private:
1455 int a;
1456 };
1457
1458 lua.new_usertype<CrashClass>("CrashClass",
1459 sol::call_constructor, sol::constructors<sol::types<>>()
1460 );
1461
1462 lua.script(R"(
1463 function testCrash()
1464 local x = CrashClass()
1465 end
1466 )");
1467
1468 for (int i = 0; i < 1000; ++i) {
1469 lua["testCrash"]();
1470 }
1471 }
1472
1473 TEST_CASE("usertype/call-initializers", "Ensure call constructors with initializers work well") {
1474 struct A {
1475 double f = 25.5;
1476
initA1477 static void init(A& x, double f) {
1478 x.f = f;
1479 }
1480 };
1481
1482 sol::state lua;
1483 lua.open_libraries();
1484
1485 lua.new_usertype<A>("A",
1486 sol::call_constructor, sol::initializers(&A::init)
1487 );
1488
1489 lua.script(R"(
1490 a = A(24.3)
1491 )");
1492 A& a = lua["a"];
1493 REQUIRE(a.f == 24.3);
1494 }
1495