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